如何使用 c++ 通过 http 发送文件
我想写一个服务器端代码。它应该适用于流行的浏览器和 wget。我的服务器检查文件是否存在,如果存在则浏览器可以下载它。但我有一些问题。 老实说,我读了很多问题答案(例如:发送使用 C 套接字的 HTTP 响应中的二进制文件),但我没有找到。我的浏览器(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-如果我不在okStatus
中写入“s”或其他内容,我的消息将无法发送。我对此一无所知。
这是 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 标头,但我没有找到。
我不希望该浏览器演示文本文件。浏览器应该下载它。如何发送可下载的文件?
抱歉,我解释的一切都很复杂。
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 << 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
关于您的第一个问题,您应该找出文件的确切大小并在
"Content-Length: xxxx\r\n"
标头中指定它。当然,你应该确保数据完全发送出去。事实上,在您的 writeF 函数中,您使用 std::string 作为缓冲区:
这不适合二进制数据。您应该分配一个正确大小的原始
char
数组:对于第二点,当您的数据不是 HTML 时,指定为 Content-Type:
text/plain
;否则,您的回车符应由
表示,而不是“\r\n”。在二进制下载的情况下,要将数据下载为文件(并且不显示在浏览器中),您应该指定
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 astd::string
as a buffer:this is not appropriate for binary data. You should allocate a raw
char
array of the right size: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
问题是这里的
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
您需要发送因为浏览器会将此文本解析为 html,而不是像操作系统解析并显示输出。您可以做的另一种方法是将所有
\n
替换为
...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 ofstrlen
Change the
writeLn(acceptSocket, buffer.c_str());
towriteLn(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>
...关于问题 1 - 如果您不想发回任何内容,请删除
okStatus
末尾的s
并指定Content-Length: 0\r标题中的 \n
Regarding question 1 - if you don't want to send any content back then remove the
s
from the end ofokStatus
and specifyContent-Length: 0\r\n
in the header