Как отправить файл с http с помощью c ++ - PullRequest
3 голосов
/ 25 мая 2011

Я хочу написать код на стороне сервера.Должен работать с популярными браузерами и wget.Мой сервер проверил, существует файл или нет, если он существует, браузер может загрузить его.Но у меня есть некоторые проблемы.Честно говоря, я прочитал много вопросов-ответов (например: Отправить двоичный файл в ответ HTTP, используя сокеты C ), но я не узнал.Мой браузер (Chrome) может получать текст.Но я не могу отправить двоичные данные или изображения и т. Д. Я изменяю заголовок в соответствии с загружаемыми файлами.Но я пока не могу отправить загружаемые файлы.

У меня есть несколько вопросов.

void *clientWorker(void * acceptSocket) {
     int newSocket = (int) acceptSocket;
     char okStatus[] = "HTTP/1.1 200 OK\r\n"
                       "Content-Type: text/html\r\n"
                       "Connection: close\r\n"
                       "Content-Length: 20\r\n"
                       "\r\n"
                       "s";
     writeLn(newSocket, okStatus);
     const char * fileName = "/home/tyra/Desktop/example.txt";
     sendF(newSocket, fileName);
}

1- Если я не напишу "s" или что-то еще вokStatus, мое сообщение не может быть отправлено.Я ничего не понимаю в этом.

Это writeLn функция:

void writeLn(int acceptSocket, const char * buffer) {
    int n = write(acceptSocket, buffer, strlen(buffer) - 1);
    if (n < 0) {
        error("Error while writing");
    }
}

Это sendF функция:

string buffer;
string line;
ifstream myfile(fileName);
struct stat filestatus;
stat(fileName, &filestatus);
int fsize = filestatus.st_size;
if (myfile.is_open()) {
    while (myfile.good()) {
        getline(myfile, line);
        buffer.append(line);
    }
    cout << buffer << endl;
}
writeLn(acceptSocket, buffer.c_str());
cout << fsize << " bytes\n";

Немного грязно,Я еще не использовал размер файла.Если я отправляю файл, я переставляю эти вещи.

2- Я могу отправить текст, и браузер демонстрирует его, но браузер не понимает новых строк.Если текстовый файл содержит (123 \ n456 \ n789), браузер демонстрирует (123456789).Я думаю, что я должен изменить заголовок Content-Type, но я не узнал.

Я не хочу, чтобы браузер отображал текстовые файлы.Браузер должен скачать его.Как я могу отправить загружаемые файлы?

Извините, я все объясняю довольно сложно.

Ответы [ 3 ]

2 голосов
/ 25 мая 2011

Что касается вашего первого вопроса, вы должны узнать точный размер файла и указать его в заголовке "Content-Length: xxxx\r\n".И, конечно же, вы должны убедиться, что данные отправлены полностью.

Действительно, в вашей функции writeF вы используете std::string в качестве буфера:

string buffer;

thisне подходит для двоичных данных.Вы должны выделить необработанный массив char правильного размера:

int fsize = file.tellg();
char* buffer = new char[fsize];
file.seekg (0, ios::beg);
file.read (buffer, size);
file.close();

Что касается второго пункта, когда ваши данные не являются HTML, укажите как Content-Type: text/plain;в противном случае возврат каретки должен быть представлен <br> вместо "\ r \ n".

В случае двоичных загрузок, чтобы данные загружались в виде файла (и не показывались в браузере),Вы должны указать

Content-Type: application/octet-stream
1 голос
/ 25 мая 2011

Проблема здесь strlen. strlen завершается, когда получает символ '\ 0'. В двоичном файле у вас будет несколько символов '\ 0'.

При чтении файла вы должны узнать размер файла. Этот размер следует использовать в int n = write(acceptSocket, buffer, strlen(buffer) - 1); вместо strlen

Измените writeLn(acceptSocket, buffer.c_str()); на writeLn(acceptSocket, buffer.c_str(), buffer.size()); и попробуйте ...

В случае 123\n456\n789 вам нужно отправить <PRE>123\n456\n789</PRE>, так как браузер будет анализировать этот текст как html, а не как ОС, анализирует и отображает вывод. Другой способ сделать это - заменить все \n на <BR> ...

0 голосов
/ 25 мая 2011

По вопросу 1 - если вы не хотите отправлять какой-либо контент назад, удалите s с конца okStatus и укажите Content-Length: 0\r\n в заголовке

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...