项目场景:
基于Mongoose搭建的Http服务器,利用Python requests模块请求上传文件
Mongoose version : v7.4
问题描述:
利用Python requests模块请求上传文件失败
upload.py:
from urllib3 import encode_multipart_formdata
import requests
def sendFile(filename, file_path):
"""
:param filename:文件的名称
:param file_path:文件的绝对路径
"""
url = "http://0.0.0.0:8000/upload" # 请求的接口地址
headers_from_data = {}
files = {'file': open(file_path,'rb')}
response = requests.post(url=url, headers=headers_from_data, files=files)
return response
if __name__=='__main__':
# 上传文件
res = sendFile("test.zip", "/home/xxxx/proj/test.zip") # 调用sendFile方法
print(res)
原因分析:
Mongoose官网提供的上传文件的示例代码:
// Send a large blob of data chunk by chunk
var sendFileData = function(name, data, chunkSize) {
var sendChunk = function(offset) {
var chunk = data.subarray(offset, offset + chunkSize) || '';
var opts = {method: 'POST', body: chunk};
var url = '/upload?offset=' + offset + '&name=' + encodeURIComponent(name);
setStatus(
'sending bytes ' + offset + '..' + (offset + chunk.length) + ' of ' +
data.length);
fetch(url, opts).then(function(res) {
if (chunk.length > 0) sendChunk(offset + chunk.length);
});
};
sendChunk(0);
};
如您所见,每个请求都有一个 URI: /upload?offset=XXX&name=YYY
与Python requests模块请求上传的URL不一致,因此Mongoose判断Python requests模块上传文件的请求是一个错误的请求,导致上传失败
解决方案:
魔改Mongoose源码,以支持Python requests请求http上传文件。
修改mg_http_upload函数,如下:
int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
const char *dir) {
char offset[40] = "", name[200] = "", path[256];
// mg_http_get_var(&hm->query, "offset", offset, sizeof(offset));
// mg_http_get_var(&hm->query, "name", name, sizeof(name));
struct mg_http_part part;
size_t oft = 0;
while((oft = mg_http_next_multipart(hm->body, oft, &part)) > 0) {
strncpy(name, part.filename.ptr, strlen(part.filename.ptr) - strlen(strchr(part.filename.ptr, '\"')));
if (name[0] == '\0') {
mg_http_reply(c, 400, "", "%s", "name required");
return -1;
} else {
FILE *fp;
snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name);
LOG(LL_DEBUG,
("%p %d bytes @ %d [%s]", c->fd, (int) part.body.len, (int) oft, name));
if ((fp = fopen(path, oft == 0 ? "wb" : "ab")) == NULL) {
mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
return -2;
} else {
fwrite(part.body.ptr, 1, part.body.len, fp);
fclose(fp);
mg_http_reply(c, 200, "", "");
return (int) part.body.len;
}
}
}
}