MSDNは、WinInet がチャンク アップロードをサポートしていないと述べています (「クライアント コードはチャンクを実行する必要があります。」)。私にとっては、転送を手動でチャンクできることを意味していました。私の意図は、 HttpAddRequestHeadersを介して "Transfer-Encoding: chunked" を追加し、 HttpAddRequestHeaders HTTP_ADDREQ_FLAG_REPLACE を介して Content-Length を削除し、 InternetWriteFile ループでチャンク エンコード ブロックにデータを書き込むことでした。問題は、Content-Length を送信しないように WinInet を納得させることができないことです。削除した後でも、「Content-Length: 0」をサーバーに送信することになり (「Transfer-Encoding: chunked」に加えて)、サーバーを混乱させます。
また、 HSR_CHUNKED フラグをHttpSendRequestExに設定しようとしました。
WinInet に Content-Length の送信をスキップさせる例はありますか?
WinHTTP がチャンク アップロードをサポートしていると主張していることは知っていますが、WinInet には他の依存関係があるため、可能であればそこで問題を解決したいと考えています。
これが私が試したコードサンプルです:
#include <windows.h>
#include <wininet.h>
#include <tchar.h>
#include <stdio.h>
bool http_putfile(HINTERNET hConnection, TCHAR* resource);
#define HOST _T("www.website.com")
#define RESOURCE _T("/path/for/resource")
int _tmain(int argc, TCHAR* argv[])
{
LPCTSTR lpszHostName = HOST;
INTERNET_PORT nServerPort = INTERNET_DEFAULT_HTTP_PORT;
DWORD dwService = INTERNET_SERVICE_HTTP;
DWORD dwFlags = NULL;
DWORD dwContext = 0;
HINTERNET hSession = InternetOpen(
argv[0],
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL,
NULL);
if(hSession != NULL)
{
HINTERNET hConnection = InternetConnect(
hSession,
lpszHostName,
nServerPort,
NULL,
NULL,
dwService,
dwFlags,
dwContext);
if(hConnection != NULL)
{
http_putfile(hConnection, RESOURCE);
InternetCloseHandle(hConnection);
}
else
{
printf("InternetConnect failed: %d\n", GetLastError());
}
InternetCloseHandle(hSession);
}
else
{
printf("InternetOpen failed: %d\n", GetLastError());
}
return 0;
}
bool http_putfile(HINTERNET hConnection, TCHAR* resource)
{
bool result = false;
HINTERNET hRequest = HttpOpenRequest(
hConnection,
_T("PUT"),
resource,
NULL,
NULL,
NULL,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_CACHE_WRITE,
0);
if(hRequest != NULL)
{
HttpAddRequestHeaders(
hRequest,
_T("Transfer-Encoding: chunked\r\n"),
-1L,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
// have tried:
// Content-Length
// Content-Length:
// Content-Length\r\n
// Content-Length:\r\n
// all with/without HTTP_ADDREQ_FLAG_ADD. Have even tried adding in a Content-Length
// and then removing it. All results show "Content-Length: 0" in the header on the wire.
if(HttpAddRequestHeaders(
hRequest,
_T("Content-Length"),
-1L,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE) == FALSE)
{
DWORD err = GetLastError();
}
// have tried both 0 here for flags as documented on msdn
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384318%28v=vs.85%29.aspx
// as well as other combinations of INITIATE/CHUNKED
if(HttpSendRequestEx(hRequest, NULL, NULL, HSR_INITIATE | HSR_CHUNKED /* 0 */, NULL))
{
DWORD wrote = 0;
char* chunks = "5\r\nCHUNK0\r\n";
if(InternetWriteFile(
hRequest,
chunks,
strlen(chunks),
&wrote) == FALSE)
{
printf("InternetWriteFile failed: %d\n", GetLastError());
}
HttpEndRequest(hRequest, NULL, 0, NULL);
}
else
{
printf("HttpSendRequestEx failed: %d\n", GetLastError);
}
InternetCloseHandle(hRequest);
}
else
{
printf("HttpOpenRequest failed: %d\n", GetLastError());
}
return result;
}