如何用C++通过HTTP协议上传文件?
How to upload file through HTTP protocol with C++?
我将使用 C++ 将文件上传到 Java spring 启动 Web 服务器。
我构建的协议如下所示(纯文本):
POST /gallery/multimedia/uploadvideo HTTP/1.1
Host: 192.168.0.133:8981
Content-Type: multipart/form-data; boundary=------boundary1804289383
Connection: keep-alive
--------boundary1804289383
Content-Type: video/mp4
Content-Disposition: form-data; name="file"; filename="1.mp4"
Content-Length: 948611
Content-Transfer-Encoding: 8bit
... binary video data here ...
--------boundary1804289383--
服务器端为Javaspring启动服务器,接口定义如下:
@PostMapping("uploadvideo")
public ResultVo uploadVideo(@RequestParam("file") MultipartFile file);
发布文件时,服务器响应代码 400,并抱怨
Required request part 'file' is not present
然而对于一个简单的HTML页面,文件上传成功,HTML页面如下:
<html>
<head></head>
<body>
<form id="form" enctype="multipart/form-data" method="post"
action="http://192.168.0.133:8981/gallery/multimedia/uploadvideo">
<input id="file" name="file" type="file" />
<input id="submit" value="submit" type="submit" />
</form>
</body>
</html>
我错过了什么?
编辑:
我试过 Postman/Chrome console/curl,所有这些工具只打印请求看起来像:
# this is from curl
POST /gallery/multimedia/uploadvideo HTTP/1.1
User-Agent: curl/7.29.0
Host: 192.168.0.133:8981
Accept: */*
Content-Length: 187
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------3c653d03b97f
我应该如何构建文件部分?有什么想法吗?
首先感谢@strupo 的建议。
通过打开 curl
的 --trace
选项并查看输出日志文件,我终于解决了这个问题。
在curl
中,它通过几个数据包发布文件:
header:
POST /gallery/multimedia/uploadvideo HTTP/1.1
User-Agent: curl/7.29.0
Host: 192.168.0.133:8981
Accept: */*
Content-Length: 13602 # you have to calculate content length first
Expect: 100-continue # very important line
Content-Type: multipart/form-data; boundary=------3c653d03b97f
然后等待服务器响应:
HTTP/1.1 100
服务器响应码100后,发送数据内容,form-dataheader在前:
--------3c653d03b97f
Content-Type: video/mp4
Content-Disposition: form-data; name="file"; filename="1.mp4"
Content-Length: 6640
Content-Transfer-Encoding: 8bit
然后是文件内容,(在我的例子中,分配了一个大内存,一次从文件读取并写入套接字),然后是下一个文件。
最终协议应该以边界线结束:
--------3c653d03b97f--
Content-Length
应该包括在 header 之后发送的所有字节。 boundary
应该在文件部分以 --
为前缀。还要注意到处的\r\n
。
我将使用 C++ 将文件上传到 Java spring 启动 Web 服务器。
我构建的协议如下所示(纯文本):
POST /gallery/multimedia/uploadvideo HTTP/1.1
Host: 192.168.0.133:8981
Content-Type: multipart/form-data; boundary=------boundary1804289383
Connection: keep-alive
--------boundary1804289383
Content-Type: video/mp4
Content-Disposition: form-data; name="file"; filename="1.mp4"
Content-Length: 948611
Content-Transfer-Encoding: 8bit
... binary video data here ...
--------boundary1804289383--
服务器端为Javaspring启动服务器,接口定义如下:
@PostMapping("uploadvideo")
public ResultVo uploadVideo(@RequestParam("file") MultipartFile file);
发布文件时,服务器响应代码 400,并抱怨
Required request part 'file' is not present
然而对于一个简单的HTML页面,文件上传成功,HTML页面如下:
<html>
<head></head>
<body>
<form id="form" enctype="multipart/form-data" method="post"
action="http://192.168.0.133:8981/gallery/multimedia/uploadvideo">
<input id="file" name="file" type="file" />
<input id="submit" value="submit" type="submit" />
</form>
</body>
</html>
我错过了什么?
编辑:
我试过 Postman/Chrome console/curl,所有这些工具只打印请求看起来像:
# this is from curl
POST /gallery/multimedia/uploadvideo HTTP/1.1
User-Agent: curl/7.29.0
Host: 192.168.0.133:8981
Accept: */*
Content-Length: 187
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------3c653d03b97f
我应该如何构建文件部分?有什么想法吗?
首先感谢@strupo 的建议。
通过打开 curl
的 --trace
选项并查看输出日志文件,我终于解决了这个问题。
在curl
中,它通过几个数据包发布文件:
header:
POST /gallery/multimedia/uploadvideo HTTP/1.1
User-Agent: curl/7.29.0
Host: 192.168.0.133:8981
Accept: */*
Content-Length: 13602 # you have to calculate content length first
Expect: 100-continue # very important line
Content-Type: multipart/form-data; boundary=------3c653d03b97f
然后等待服务器响应:
HTTP/1.1 100
服务器响应码100后,发送数据内容,form-dataheader在前:
--------3c653d03b97f
Content-Type: video/mp4
Content-Disposition: form-data; name="file"; filename="1.mp4"
Content-Length: 6640
Content-Transfer-Encoding: 8bit
然后是文件内容,(在我的例子中,分配了一个大内存,一次从文件读取并写入套接字),然后是下一个文件。
最终协议应该以边界线结束:
--------3c653d03b97f--
Content-Length
应该包括在 header 之后发送的所有字节。 boundary
应该在文件部分以 --
为前缀。还要注意到处的\r\n
。