使用 Wininet 上传文件时如何添加正确的 Content-Type? (HTTP 放置)
Posted
技术标签:
【中文标题】使用 Wininet 上传文件时如何添加正确的 Content-Type? (HTTP 放置)【英文标题】:How to add correct Content-Type when uploading file with Wininet? (HTTP PUT) 【发布时间】:2015-09-30 04:17:02 【问题描述】:我正在将带有Wininet 的文件上传到带有HTTP PUT 的Sharepoint 服务器。然而,即使我指定了一个带有.xlsx
扩展名的文件名,我在Sharepoint 服务器上得到了一个名为.xlsx
的文件,但是在下载它时,它得到了一个.zip
扩展名。此外,在 Sharepoint 上,文件旁边没有 Excel 小图标,而是一个更通用的图标。我已经尝试了使用 HttpAddRequestHeaders 和 HttpSendRequest 设置 Content-type(“mime-type”)的所有组合,我可以想出。
以下代码上传文件,但 Sharepoint 获取的内容类型错误:
static int upload_file_to_sharepoint(LPCSTR filename, LPCSTR server, LPCSTR location)
HINTERNET hIntrn = InternetOpenA(
"magic",
INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY,
NULL,
NULL,
0
);
if (!hIntrn)
return printf("No Internet connection: %li.\n", GetLastError());
HINTERNET hConn = InternetConnectA(
hIntrn,
server,
INTERNET_DEFAULT_HTTPS_PORT,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
NULL
);
if (!hConn)
return printf("Connection to update server failed: %li.\n", GetLastError());
DWORD dwOpenRequestFlags =
INTERNET_FLAG_KEEP_CONNECTION |
INTERNET_FLAG_NO_COOKIES |
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_NO_UI |
INTERNET_FLAG_RELOAD;
PCSTR rgpszAcceptTypes[] =
"text/*",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
NULL
;
HINTERNET hReq = HttpOpenRequestA(
hConn,
"PUT",
location,
"HTTP/1.1",
NULL,
rgpszAcceptTypes,
dwOpenRequestFlags,
NULL
);
HANDLE hFile = CreateFileA(
filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (NULL == hFile)
ExitProcess(1);
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL == hMap)
ExitProcess(1);
LPVOID lpvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
DWORD dwFileSize = GetFileSize(hFile, NULL);
CHAR mimetype[1024];
sprintf(
mimetype,
"Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
//"Content-Type: application/vnd.ms-excel\r\n"
);
if (!HttpAddRequestHeadersA(hReq, mimetype, -1, HTTP_ADDREQ_FLAG_REPLACE))
printf("Failed adding mime header\n");
if (!HttpSendRequestA(
hReq,
NULL,// "Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
0, //-1,
lpvFile,
dwFileSize))
printf("HttpSendRequest failed: %li.\n", GetLastError());
UnmapViewOfFile(lpvFile);
CloseHandle(hMap);
CloseHandle(hFile);
printf("Uploaded file to http://%s%s\n", server, location);
return 0;
我用 Fiddler 捕获了标题,得到了这个:
PUT http://x.com/CENSORED/a.xslx HTTP/1.1
Accept: text/*, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Disposition: attachment; filename="a.xlsx"
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
User-Agent: magic
Host: censored
Content-Length: 772303
Connection: Keep-Alive
Pragma: no-cache
HTTP/1.1 200 OK
Cache-Control: private,max-age=0
Content-Length: 0
Expires: Tue, 15 Sep 2015 08:43:16 GMT
Last-Modified: Wed, 30 Sep 2015 08:43:16 GMT
ETag: "0DC262D0-83AE-489A-90CD-EB23B284A3B3,14"
Server: Microsoft-IIS/7.5
SPRequestGuid: 6aba173e-41db-4b14-b7df-7714c54db282
X-SharePointHealthScore: 0
ResourceTag: rt:0DC262D0-83AE-489A-90CD-EB23B284A3B3@00000000014
Public-Extension: http://schemas.microsoft.com/repl-2
X-Powered-By: ASP.NET
MicrosoftSharePointTeamServices: 14.0.0.7145
X-MS-InvokeApp: 1; RequireReadOnly
ServerName: Xcensored
Date: Wed, 30 Sep 2015 08:43:16 GMT
【问题讨论】:
您似乎没有向服务器提供文件名,也许与它有关? @JonathanPotter,这是在HttpOpenRequestA( hConn, "PUT", location,
中完成的AFAIK,其中location
是URL 中指出文件名的部分。实际上在文件列表中的服务器上称为“output.xslx”,但下载时我得到“output.zip”。我也可以在浏览器中上传一个文件,然后我得到 两个 文件,称为 output.xlsx。后者作为 xlsx 文件下载。
我认为内容类型应该是application/vnd.ms-excel
,因为你已经尝试过了,但也可以尝试添加Content-Disposition: attachment; filename="filename.xlsx"
那行不通。它运行时没有运行时警告但没有雪茄: if (!HttpAddRequestHeadersA( hReq, "Content-Disposition: attachment; filename=\"a.xlsx\"", (DWORD)-1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD )) printf("Failed添加 mime 类型的标题\n"); if (!HttpAddRequestHeadersA( hReq, "Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", (DWORD)-1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD )) printf("@JonathanPotter");
【参考方案1】:
因此,如果您将文件上传为 .xlsx
而不是 .xslx
会有所帮助...
代码现在可以运行,看起来像这样,不需要特殊的标头,这与我在网上找到的其他示例一致:
static int upload_file_to_sharepoint(LPCSTR filename, LPCSTR server, LPCSTR location)
HINTERNET hIntrn = InternetOpenA(
"magic",
INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY,
NULL,
NULL,
0
);
if (!hIntrn)
return printf("No Internet connection: %li.\n", GetLastError());
HINTERNET hConn = InternetConnectA(
hIntrn,
server,
INTERNET_DEFAULT_HTTPS_PORT,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,
NULL
);
if (!hConn)
return printf("Connection to update server failed: %li.\n", GetLastError());
DWORD dwOpenRequestFlags =
INTERNET_FLAG_KEEP_CONNECTION |
INTERNET_FLAG_NO_COOKIES |
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_NO_UI |
INTERNET_FLAG_RELOAD;
HINTERNET hReq = HttpOpenRequestA(
hConn,
"PUT",
location,
"HTTP/1.1",
NULL,
NULL,
dwOpenRequestFlags,
NULL
);
HANDLE hFile = CreateFileA(
filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (NULL == hFile)
ExitProcess(1);
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL == hMap)
ExitProcess(1);
LPVOID lpvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (!HttpSendRequestA(
hReq,
NULL,
0,
lpvFile,
dwFileSize))
printf("HttpSendRequest failed: %li.\n", GetLastError());
UnmapViewOfFile(lpvFile);
CloseHandle(hMap);
CloseHandle(hFile);
printf("Uploaded file to http://%s%s\n", server, location);
return 0;
【讨论】:
以上是关于使用 Wininet 上传文件时如何添加正确的 Content-Type? (HTTP 放置)的主要内容,如果未能解决你的问题,请参考以下文章
尝试使用 wininet 将文件上传到 FTP 时遇到问题 [Id 返回 1 退出状态]