CGI на Delphi. Проблема с file upload

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Joker-jar, 8 Sep 2007.

  1. Joker-jar

    Joker-jar Elder - Старейшина

    Joined:
    11 Mar 2007
    Messages:
    581
    Likes Received:
    205
    Reputations:
    37
    Пишу скрипт для загрузки файлов на сервер:

    Code:
    program upload;
    
    {$APPTYPE CONSOLE}
    {$E cgi}
    
    uses
      windows;
    
    var
      ch: char;
      s: string;
      buffer: PChar;
      contlength, ecode, i: integer;
    
    procedure putfile(filename: string);
    var
      f: textfile;
    begin
      assignfile(f, filename);
      reset(f);
        while not (eof(f)) do
          begin
            readln(f,s);
            writeln(s);
          end;
      closefile(f);
    end;
    
    begin
      putfile('headers.txt');
      writeln;
      getmem(buffer, 256);
      if GetEnvironmentVariable('CONTENT_LENGTH',buffer,256) > 0 then
        begin
          val(buffer,contlength,ecode);
          s := '';
          for i := 1 to contlength do
            begin
              read(ch);
              s := s + ch;
            end;
          writeln(s);
          exit;
        end
      else
        begin
          putfile('top.txt');
          putfile('form.txt');
          putfile('bottom.txt');
        end;
      freemem(buffer);
    end.
    headers.txt :

    Content-Type: text/html

    top.txt :

    <html>
    <head>
    <title>File Upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
    </head>
    <body>


    form.txt :

    <style>
    .tb td {padding: 5px}
    </style>
    <form method="post" encrypte="multipart/form-data">
    <input type="hidden" name="checked" value="yes">
    <table class="tb">
    <tr><td><input type="file" name="filename"></td></tr>
    <tr><td><input type="submit" value="Ok"></td></tr>
    </table>
    </form>


    bottom.txt :

    </body>
    </html>


    В итоге скрипт показывает строку POST параметров, а само содержимое файла нет. + CONTENT_LENGTH показывает размер POST данных, не учитывая размер файла. Что не так?
     
  2. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Мо моему переменная s инициализируется позже чем идет первое обращение к ней. В начале тела программы стоит putfile('headers.txt'); в которой уже нужна s. Остальное вроде аналогично. А может я и гоню... :)
     
  3. Joker-jar

    Joker-jar Elder - Старейшина

    Joined:
    11 Mar 2007
    Messages:
    581
    Likes Received:
    205
    Reputations:
    37
    Code:
    procedure putfile(filename: string);
    var
      s: string;
      f: textfile;
    begin
      assignfile(f, filename);
      reset(f);
        while not (eof(f)) do
          begin
            readln(f,s);
            writeln(s);
          end;
      closefile(f);
    end;
    Вот так правильней будет. Но сути проблемы не решает
     
  4. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Не будет правильней. Объявление переменой в процедуре не инициализирует ее! У нас идет обращение к переменой s в процедуре putfile('headers.txt'); в строке readln(f,s);. Но процедура putfile('headers.txt'); расположена в самом начале тела программы
    begin
    putfile('headers.txt');
    writeln;
    getmem(buffer, 256);
    if GetEnvironmentVariable .....

    и переменная s в этот момент еще не инициализирована, т.е. ни чему не равна. ЕЕ инициализация происходит уже НИЖЕ в строках
    s := '';
    for i := 1 to contlength do
    begin
    read(ch);
    s := s + ch;
    .....
    А значит в начале програмы процедура putfile('headers.txt'); выполняется с неполными данными...
    нету s. Она хоть и объявлена в процедуре но не инициализирована... Оттрасируй програмку и посмотри на значение s при выполнении putfile('headers.txt'); вначале...
     
  5. Joker-jar

    Joker-jar Elder - Старейшина

    Joined:
    11 Mar 2007
    Messages:
    581
    Likes Received:
    205
    Reputations:
    37
    Тогда глобальная пусть будет не s а sd, s - локальная, там все нормально (putfile(filename: string) - подает содержимое файла filename на стандартный ввод, работает без глюков). В sd считываются данные со стандартного вывода, где, по идее, должно быть содержимое закачиваемого файла, но там кроме checked=yes&filename=1.txt ничего нет. Как добраться до него? Просьба помочь по делу.
     
    #5 Joker-jar, 8 Sep 2007
    Last edited: 8 Sep 2007
  6. W!z@rD

    W!z@rD Борец за русский язык

    Joined:
    12 Feb 2006
    Messages:
    973
    Likes Received:
    290
    Reputations:
    43
    Joker-jar, а не проще ли использовать ApacheModule?
    с этим модулем разобраться проще некуда...
    не мучайте себя...
     
  7. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Да ДжокерДжар, я затупил с переменной s.... короче я неправ. Пытаюсь разобраться с програмкой... повторно. Скрипты для веба на дельфи это для меня новинка.
     
  8. Joker-jar

    Joker-jar Elder - Старейшина

    Joined:
    11 Mar 2007
    Messages:
    581
    Likes Received:
    205
    Reputations:
    37
    Это не для практической, а для учебной цели (такое задание). А встал в самом начале :(
     
  9. Joker-jar

    Joker-jar Elder - Старейшина

    Joined:
    11 Mar 2007
    Messages:
    581
    Likes Received:
    205
    Reputations:
    37
    Короче, почитал доки, поспрашивал задротов и вот что выяснил: Apache, прежде чем отдать http-запрос CGI-скрипту, вырезает оттуда блок данных файла и сохраняет его в свою временную директорию. Далее скрипт должен узнать путь к этой директории (через переменные окружения 'TEMP', 'TMP') и оттуда скопировать полученный файл / сделать с ним что угодно. Но тут снова появилось несколько вопросов. Никогда не слышал, чтоб у Apache была какая-то временная директория, что подтвердилось просмотром httpd.conf - никакого похожего параметра не нашел. Во-вторых, в переменных окружения отсутствует этот самый путь. У IIS есть, а вот у Apache нет (хотя это может быть и потому, что он не настроен как надо). Кто-нибудь знает, предусмотрена ли в httpd какая-нибудь команда, задающая путь ко временному каталогу. Второй вопрос - как Apache обзывает эти самые файлы, ведь реальные клиентские имена он не знает?
     
  10. Joker-jar

    Joker-jar Elder - Старейшина

    Joined:
    11 Mar 2007
    Messages:
    581
    Likes Received:
    205
    Reputations:
    37
    С этим всем разобрался. Теперь надо парсить multipart... Вопрос закрыт
     
    #10 Joker-jar, 15 Sep 2007
    Last edited: 15 Sep 2007
  11. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Joker-jar, для тебя может и закрыт. Поделись пожалуйста ответом.... где все таки временные каталоги и какие имена у файлов. А может ты иначе сделал?
     
  12. Joker-jar

    Joker-jar Elder - Старейшина

    Joined:
    11 Mar 2007
    Messages:
    581
    Likes Received:
    205
    Reputations:
    37
    Не, оказывается, сервер ничего никуда не вырезает, все остается в HTTP. Я просто неправильно как-то сделал форму отправки. Если сделать так:
    HTML:
    .formtable td
    	{
    		padding 3px 5px 3px 5px;
    	}
    </style>
    <form action="/cgi-bin/test.cgi" enctype="multipart/form-data" method="post">
    <table class="formtable">
    <tr><td><input type="file" name="textfile" style="width: 250px"></td></tr>
    <tr><td><input type="file" name="binfile" style="width: 250px"></td></tr>
    <tr><td><input type="submit" value="Ok" style="width: 60px"></td></tr>
    </table>
    </form>
    а в test.cgi что-нибудь типа:
    Code:
    i: integer;
    c: char
    ......
    for i := 1 to {CONTENT_LENGTH} do
      begin
        read(c);
        write(c);
      end;
    Как видно, все там есть. Осталось тока это сохранить куда надо. А вот с этим проблемы, но это уже другая тема.