如何使用WinHttp获取下载文件的原始文件名与Content-Length头信息
WinHttp文件下载功能问题解决指南
1 获取响应中的原始文件名
文件原始文件名存储在响应头的Content-Disposition字段中,现有代码中给请求添加Content-Disposition头的逻辑属于多余操作,可直接删除。获取解析流程如下:
- 调用
WinHttpQueryHeaders时传入WINHTTP_QUERY_CONTENT_DISPOSITION参数获取该响应头的值 - 解析头内容提取
filename参数值,若响应未返回该头,则从请求URL的路径末尾提取文件名作为兜底方案
代码示例:
WCHAR* pDisposition = NULL; DWORD dwDispositionSize = 0; // 先查询所需缓冲区大小 WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_DISPOSITION, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwDispositionSize, WINHTTP_NO_HEADER_INDEX); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pDisposition = new WCHAR[dwDispositionSize / sizeof(WCHAR)]; if(WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_DISPOSITION, WINHTTP_HEADER_NAME_BY_INDEX, pDisposition, &dwDispositionSize, WINHTTP_NO_HEADER_INDEX)) { std::wstring dispStr(pDisposition); size_t filenamePos = dispStr.find(L"filename="); if(filenamePos != std::wstring::npos) { std::wstring fileName = dispStr.substr(filenamePos + 9); // 移除文件名前后的引号 if(fileName.front() == L'"') fileName = fileName.substr(1); if(fileName.back() == L'"') fileName.pop_back(); // 此处拿到的fileName即为原始文件名,可直接传入CreateFile接口 } } delete[] pDisposition; } // 兜底逻辑:无Content-Disposition头时可调用WinHttpQueryHeaders传入WINHTTP_QUERY_URL拿到请求URL,截取路径最后一段作为文件名
2 获取Content-Length字段
使用WINHTTP_QUERY_CONTENT_LENGTH参数即可获取,针对大于4G的大文件建议使用64位变量存储数值:
WCHAR* pContentLen = NULL; DWORD dwLenSize = 0; ULONGLONG contentLength = 0; WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwLenSize, WINHTTP_NO_HEADER_INDEX); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pContentLen = new WCHAR[dwLenSize / sizeof(WCHAR)]; if(WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH, WINHTTP_HEADER_NAME_BY_INDEX, pContentLen, &dwLenSize, WINHTTP_NO_HEADER_INDEX)) { contentLength = _wcstoui64(pContentLen, NULL, 10); } delete[] pContentLen; }
3 现有代码优化点
- 删除无效逻辑:
WinHttpAddRequestHeaders添加Content-Disposition的代码、WinHttpSendRequest第二个参数传Content-Disposition的代码均无实际作用,可直接删除 - 调整
CreateFile调用时机:需在拿到原始文件名之后再调用CreateFile,不要在处理响应头之前就创建路径写死的文件 - 补充资源释放:现有代码中获取原始响应头时分配的
lpOutBuffer未释放,会造成内存泄漏
内容的提问来源于stack exchange,提问作者Nikita Pavlenko
相关产品推荐
相关产品推荐

