async_download 没有写入内容到文件
kiraYuukiAsuna opened this issue · 5 comments
相关代码,目前我是手动写入文件的
// Download the file in chunks of 100MB
const size_t chunk_size = 100 * 1024 * 1024; // 100MB
for (size_t start = 0; start < bytes_total; start += chunk_size) {
size_t end = std::min(start + chunk_size - 1, bytes_total - 1);
SEELE_INFO_TAG(__func__, "{}",
"Download Range: " + std::to_string(start) + "-" + std::to_string(end) + "/" + std::to_string
(bytes_total));
std::string rangeFilePath = localSaveFilePath + "_range=" + std::to_string(start) + "-" + std::to_string(end);
auto result = co_await client.async_download(uri, rangeFilePath, std::to_string(start) + "-" + std::to_string(end));
if (!result.net_err && result.status == 206) {
bytes_received += end - start + 1;
std::ofstream ofstream(rangeFilePath, std::ios::binary);
if(!ofstream.is_open()) {
SEELE_INFO_TAG(__func__, "{}", "Open File Error! File:" + rangeFilePath);
std::pair<ReturnWrapper, std::string> ret{
{
false, ErrorCode::AccessFileFailed,
"Open File Error! File:" + rangeFilePath
},
""
};
co_return ret;
}
ofstream << result.resp_body;
ofstream.close();
rangeFiles.push_back(rangeFilePath);
}
else {
SEELE_INFO_TAG(__func__, "{}", "Http Response Error!" + result.net_err.message());
std::pair<ReturnWrapper, std::string> ret{
{
false, ErrorCode::HttpResponseError,
"Http Response Error!" + result.net_err.message()
},
""
};
co_return ret;
}
}
把返回的http 头输出一下,看一下是什么格式返回的,如果是chunked或者multipart则会下载到文件,否则是直接放body里面的,如果在body里面,那你就取出来存文件吧。
另外,返回206有点奇怪,206是重定向,重定向的url在http header里面,cinatra不会自动根据重定向url去请求,需要你手动去连接新的url并发请求。
谢谢您的回复!
HTTP 206 Partial Content 成功状态响应代码表示请求已成功,并且主体包含所请求的数据区间,该数据区间是在请求的 Range 首部指定的。
如果只包含一个数据区间,那么整个响应的 Content-Type 首部的值为所请求的文件的类型,同时包含 Content-Range 首部。
如果包含多个数据区间,那么整个响应的 Content-Type 首部的值为 multipart/byteranges ,其中一个片段对应一个数据区间,并提供 Content-Range 和 Content-Type 描述信息
在我的这个例子中是只包含一个Range数据区间,响应code=206Partial Content,响应的Content-Type值为application/octet-stream,具体请求和响应的头部信息可参考下面Postman的截图:
所以应该是Content-Type值为application/octet-stream的时候cinatra默认不会写到文件而是会写到返回的body中吧,我以为不管什么都会写到文件的呢,这样的话那我就手动写入到文件吧,其实还更方便了,我可以控制将多次请求的文件数据片段写到一个文件里,不然默认这个async_download如果写到文件里我还需要将多次下载得到的多个文件拼接起来,不过感觉我好像不应该用这个download函数,直接用get就好了哈哈。
感谢您的回复,解答了我的疑问!
所以应该是Content-Type值为application/octet-stream的时候cinatra默认不会写到文件而是会写到返回的body中吧,我以为不管什么都会写到文件的呢,这样的话那我就手动写入到文件吧,其实还更方便了,我可以控制将多次请求的文件数据片段写到一个文件里,不然默认这个async_download如果写到文件里我还需要将多次下载得到的多个文件拼接起来,不过感觉我好像不应该用这个download函数,直接用get就好了哈哈。
感谢您的回复,解答了我的疑问!
是的,只有chunked和multipart格式才会写文件,因为这两种格式不会有content-length字段(multipart 可以有但不是http协议要求的,即使有长度可能是几个G的大文件也不适合放内存),需要流式读取到结束符为止。
另外我记错了301/302才是重定向,206是部分内容。