开发者

How to send a file with http with c++

I want to write a server side code. It should work with popular browsers and wget. My server check that file exists or not, if exists then browser can download it. But I have some problems. Honestly, I read lots of question-answer (for example: Send binary file in HTTP response using C sockets) but I didn't find out. My browser (Chrome) can get text. But I cannot send any binary data or images etc. I am changing header according to downloading files. But I cannot send a downloadable files yet.

I have some questions.

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- If I wouldn't write "s" or something else inokStatus, my message cannot send. I don't understand anything of this.

This is writeLn function :

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

This is sendF function :

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 <&l开发者_运维问答t; endl;
}
writeLn(acceptSocket, buffer.c_str());
cout << fsize << " bytes\n";

A little messy. I haven't used file size yet. If I send a file, then I rearrange these things.

2- I can send text and browser demonstrates it but browser didn't understand new lines. If text file contains (123\n456\n789), browser demonstrates (123456789). I think I should change Content-Type header, but I didn't find out.

I don't want that browser demonstrates text files. Browser should download it. How can I send downloadable files?

Sorry, I explain everything pretty complicated.


As to your first question, you should find out the exact size of the file and specify it in your "Content-Length: xxxx\r\n" header. And, of course, you should ensure that the data is sent completely out.

Indeed, in your writeF function you use a std::string as a buffer:

string buffer;

this is not appropriate for binary data. You should allocate a raw char array of the right size:

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

As to the second point, when your data is not HTML, specify as Content-Type: text/plain; otherwise, your carriage return should be represented by <br> instead of "\r\n".

In case of binary downloads, to have the data download as a file (and not shown in the browser), you should specify

Content-Type: application/octet-stream


The issue is strlen here. strlen terminates when it gets a '\0' character. In binary file you will have a number of '\0' characters.

While reading the file you should find out the file size. This size should be used in int n = write(acceptSocket, buffer, strlen(buffer) - 1); in place of strlen

Change the writeLn(acceptSocket, buffer.c_str()); to writeLn(acceptSocket, buffer.c_str(), buffer.size()); and try...

For the case of 123\n456\n789 you need to send <PRE>123\n456\n789</PRE> as browser will parse this text as html and not like the OS parses and shows the output. The other way you can do is replace all \n with <BR> ...


Regarding question 1 - if you don't want to send any content back then remove the s from the end of okStatus and specify Content-Length: 0\r\n in the header

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜