Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Закачка файла спомощью C++ stdin и cgi?

20K
06 мая 2007 года
Finder
37 / / 06.05.2007
Задача: закачать несколько файлов на сервер спомощью cgi сценария написаного на С++.
Пока что я написал закачку одного файла.

НО вот проблема: если в файле текст английский или руский - закачивается нормально, а если закачивать маленькую картинку, то первых несколько десятков "ироглифов" заканчивается нормально а дальше идут одни буквы "я":( .

В чем тут может быть проблема? Может я не правильно читаю из stdin?

вот код html странички:
[HTML]
<html>
<body>
<form action="/cgi/loader.exe" enctype=multipart/form-data method=post>
<input type=file name='file1' ><br>
<!--
<input type=file name='file2' ><br>
<input type=file name='file3' ><br>
<input type=file name='file4' ><br>
-->
<input type=submit>
</form>
</body>
</html>
[/HTML]

Вот сишный код:
Код:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define term_size 200
#define header_size 400

int get_header(char *tmp_header)
   {
     int stop,tmp_count;
     char ch;
     for (tmp_count=0,stop=0;((stop==0)&&(tmp_count<header_size));tmp_count++)
    {
      ch=fgetc(stdin);
      tmp_header[tmp_count]=ch;
      if (tmp_count>4)
        {
          if ((tmp_header[tmp_count-1]=='\n')&&(tmp_header[tmp_count]=='\n'))
        {
          stop=1;
          tmp_header[tmp_count+1]=0;
        }
          if ((tmp_header[tmp_count-2]=='\n')&&(tmp_header[tmp_count-1]=='\r')&&(tmp_header[tmp_count]=='\n'))
        {
          stop=1;
          tmp_header[tmp_count+1]=0;
        }
        }
    }
     return 1;
   }
int get_filename(char *tmp_header, char *filename)
   {
     int i;
     char *ptr;
     ptr=strstr(tmp_header,"filename=");

     for (;*ptr!='"';ptr++) { }
     ptr++;
     for (i=0;((i<29)&&(*ptr!='"'));ptr++)
    {
      if ((*ptr=='\\')||(*ptr=='/'))
        {
         i=0;
        }
      if ((*ptr!='\\')&&(*ptr!='/')&&(*ptr!='"'))
        {
          filename=*ptr;
          i++;
        }
      filename=0;
    }
     return 1;
   }
int get_filebody(char *terminator,char *filename,long int toread)
   {
     int i,stop;
     long int readed;
     int term_len=strlen(terminator);
     char *buffer=(char *)malloc(term_len+1);
     buffer[0]=0;
     readed=0;
     char ch;
     FILE *fp;
     fp=fopen(filename,"w");
     for (i=0,stop=0;stop==0;)
    {
      ch=fgetc(stdin);
      readed++;
      if (terminator==ch)
        {
          buffer=ch;
          buffer[i+1]=0;
          i++;
        }
      else
          {
        if (strlen(buffer)==0)
          {
            //write ch only
            fputc(ch,fp);
          }
        else
            {
              //write buffer and ch
              fwrite(buffer,strlen(buffer),1,fp);
              fputc(ch,fp);
              buffer[0]=0;
              i=0;
            }
          }
      if (term_len==i+1)
        {
          stop=1;
        }
      if (readed>=toread)
        {
          if (strlen(buffer)>0)
        {
          fwrite(buffer,strlen(buffer),1,fp);
        }
          stop=1;
        }
    }
     fclose(fp);
     return 1;
   }
int main()
   {
    printf("Content-type: text/html\n");
    printf("Pragma: no-cache\n");
    printf("\n");
    char *REQUEST_METHOD=getenv("REQUEST_METHOD");
    char *CONTENT_LENGTH=getenv("CONTENT_LENGTH");

    int cmp_rez=strcmp(REQUEST_METHOD,"POST");
    if (cmp_rez==0)
      {
    int i;
    long int num_of_bytes=atoi(CONTENT_LENGTH);
   
    char terminator[term_size];
    strset(terminator,'1');
    char ch;
   
    int tmp_count;
    int stop;

    for (tmp_count=0,stop=0;((stop==0)&&(tmp_count<term_size));tmp_count++)
       {
         ch=fgetc(stdin);
         terminator[tmp_count]=ch;
         if (tmp_count>5)
           {
         if (terminator[tmp_count]=='\n')
           {
             stop=1;
             terminator[tmp_count]=0;
           }
           }
       }
    long int term_len=strlen(terminator);
   
    //printf("CONTENT_LENGTH= %i\n",num_of_bytes);
    //printf("terminator= %s<br>\nlenght_t:%i<br>\n",terminator,term_len);

    char tmp_header[header_size];
    strset(tmp_header,'1');
    get_header(tmp_header);
    char filename[30]="";
    get_filename(tmp_header,filename);
    get_filebody(terminator,filename,num_of_bytes-term_len-strlen(tmp_header));
      }
    return 1;
   }
20K
08 мая 2007 года
Finder
37 / / 06.05.2007
Вопрос остается все еще актуальным.
текстовые данные приходят нормально, а данные из jpg сначала приходят правильно а потом почемуто все заменяются буквами я.
Вот маленький код упростил для большей наглядности:
Код:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
   {
    printf("Content-type: text/html\n");
    printf("Pragma: no-cache\n");
    printf("\n");
    char *REQUEST_METHOD=getenv("REQUEST_METHOD");
    char *CONTENT_LENGTH=getenv("CONTENT_LENGTH");
    int cmp_rez=strcmp(REQUEST_METHOD,"POST");
    if (cmp_rez==0)
      {
    long int i;
    char ch;
    long int num_of_bytes=atoi(CONTENT_LENGTH);
    FILE *fp;
    fp=fopen("recived.dat","w");
    for (i=0;i<num_of_bytes-100;i++)
       {
         ch=fgetc(stdin);
         fputc(ch,fp);
       }
    fclose(fp);
      }
    return 1;
   }

ЗЫ: возможно надо уточнить для когото один момент: для демонстрации надо поставить на веб сервер, скомпилированую
екзешку положить в каталог для cgi приложений и послать ей с помощью браузера и приведеного выше html кода файлик сначала
текстовый (посмореть результат в файле recived.dat)а потом jpg(посмореть результат в файле recived.dat).

ЗЗЫ: Может эта тема больше подходит для раздела "Web программирование"?
5
08 мая 2007 года
hardcase
4.5K / / 09.08.2005
Насколько я знаю тип контента text/html никак не связан с картинками.
Попробуй поставить jpeg/image.
20K
08 мая 2007 года
Finder
37 / / 06.05.2007
Цитата: hardcase
Насколько я знаю тип контента text/html никак не связан с картинками.
Попробуй поставить jpeg/image.



Эта замена ничего не меняет(на всякий случай проверил), так как та строка для вебсервера а я пишу в файл.

350
11 мая 2007 года
cheburator
589 / / 01.06.2006
Как-то ты перемешал функции C и потоки C++. Используй уж что-то одно.
И вообще, ты уверен, что stdin/stdout работают с двоичными данными?
Создай объект типа ifstream, читай оттуда операторами >> (если писать в стиле С++), или же работай с помощью fgetc, но не потоками С++... Некрасиво это :)
И еще пара рекомендаций.
Во-первых, не пиши tmp_count++, пиши ++tmp_count, поскольку прединкремент работает быстрее.
Во-вторых, в записи
 
Код:
((stop==0)&&(tmp_count<header_size))
в одном из циклов - ни одна скобка не является обязательной. stop==0 && tmp_count<header_size тоже прокатит.
2.2K
11 мая 2007 года
e1vin
153 / / 04.06.2006
Цитата: cheburator
Во-первых, не пиши tmp_count++, пиши ++tmp_count, поскольку прединкремент работает быстрее.



Быстрее-то быстрее, а вот только если в цикле нужно пройтись от 0 до 100, что ж ты с прединкрементом будешь писать так?

 
Код:
for ( int i = -1; i <= 100; ++i ) { ... }


:D
5
11 мая 2007 года
hardcase
4.5K / / 09.08.2005
Цитата: e1vin
Быстрее-то быстрее, а вот только если в цикле нужно пройтись от 0 до 100, что ж ты с прединкрементом будешь писать так?
 
Код:
for ( int i = -1; i <= 100; ++i ) { ... }


А теперь выведи в цикле i на консоль.

Учи матчасть!

3
11 мая 2007 года
Green
4.8K / / 20.01.2000
Цитата: cheburator

И еще пара рекомендаций.
Во-первых, не пиши tmp_count++, пиши ++tmp_count, поскольку прединкремент работает быстрее.


Цитата: e1vin
Быстрее-то быстрее, а вот только если в цикле нужно пройтись от 0 до 100, что ж ты с прединкрементом будешь писать так?
 
Код:
for ( int i = -1; i <= 100; ++i ) { ... }


М-да... удивили оба автора... :\

92
18 мая 2007 года
Тень Пса
2.2K / / 19.10.2006
выведи твой результат не в файл, а в браузер и ты поймешь, правильно закачалась картинка или нет...

 
Код:
Content-type: image/jpeg\n\n


при закачке, читай Content-length тогда точно будешь знать когда нужно прервать чтение STDIN...

заголовок от данных отделяется \n\n.....

вроде бы так. надеюсь поможет. код посмотреть не смог подробненько... извиняй если чего не так :)
20K
26 мая 2007 года
Finder
37 / / 06.05.2007
Цитата: Тень Пса
выведи твой результат не в файл, а в браузер и ты поймешь, правильно закачалась картинка или нет...

 
Код:
Content-type: image/jpeg\n\n


при закачке, читай Content-length тогда точно будешь знать когда нужно прервать чтение STDIN...

заголовок от данных отделяется \n\n.....

вроде бы так. надеюсь поможет. код посмотреть не смог подробненько... извиняй если чего не так :)



Все это так но вот проблема оказалась в том что из стандартного потока ввода(stdin) данные читаются в текстовом режиме, в связи с этим некоторые байты искажаются при чтении (принимаются за управляющие).

Цитата: cheburator

И вообще, ты уверен, что stdin/stdout работают с двоичными данными?


Не уверен, но как то ведь написали разработчики языка PHP загрузку файлов, PHP насколько мне известно на С разработали.
Уже обыскался искать, не знаю как перевести стандартный поток ввода в бинарный режим чтения.

92
27 мая 2007 года
Тень Пса
2.2K / / 19.10.2006
эт если ты из cin читаешь :)

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.13


а эт если пользуешь stdin (из stdio.h)
http://www.cplusplus.com/reference/clibrary/cstdio/
350
31 мая 2007 года
cheburator
589 / / 01.06.2006
Цитата: Green
М-да... удивили оба автора... :\



Что удивительного?
Постинкремент, по идее, запоминает старое значение объекта, после чего совершает действие над объектом и возвращает старое значение.
Прединкремент же просто выполняет действие и возвращает *this.
Как видим, в постинкременте тратится время на создание объекта. Это касается, кстати, и простых типов, компилятор может и не соптимизировать это...
А если объект с некопируемой семантикой (noncopyable)? Постинкремента не будет вообще?
Читаем http://www.gotw.ca/gotw/055.htm:

 
Код:
// Canonical form of postincrement:
    T T::operator++(int)
    {
      T old( *this ); // remember our original value
// Примечание Чебуратора. Здесь-то и тратится лишнее время
      ++*this;        // always implement postincrement
                      //  in terms of preincrement
      return old;     // return our original value
    }
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог