당신의 MIME 경계선이 잘못 : 다음은 코드입니다. RFC 2046을 읽으십시오. 콘텐츠 데이터의 경계선은 -
문자로 시작하고 헤더의 boundary
매개 변수 (끝 경계선의 경우 그 다음에 두 개 이상, -
자)가 지정된 텍스트로 시작됩니다.
콘텐츠 데이터에서 사용중인 경계선에 -
문자가 2 개 있습니다. boundary
헤더에 27 개의 최상위 대시가 있으므로 콘텐츠에 29 개의 대시가 필요하며 그렇지 않은 경우 27 개가 필요합니다.
또한 입력 파일의 크기가 정확히 1023 바이트라고 가정합니다. 그러나 더 중요한 것은 CreateFile()
호출에서 오류 처리를 수행하지 않아 파일이 실제로 열려 있는지 또는 ReadFile()
호출에서 오류 처리가 수행되어 데이터가 실제로 읽혀지고 있는지 확인합니다 (힌트 : 네 번째 매개 변수 은은 5 번째 매개 변수가 NULL 일 때 NULL입니다.)
전체 파일 (음, 최대 1023 바이트, 어쨌든)을 메모리로 읽은 다음 보내려고합니다. 적어도 실제 파일 크기를 얻으려면 GetFileSize()
을 사용하고 그에 따라 szData
을 할당하고 직접 읽어 들여야합니다. szBuffer
은 전혀 필요하지 않습니다.
코드에 다른 사소한 오류가 있습니다. 더이 대신 같은 것을 시도 등
, 메모리 누수, sizeof()
을 오용 파일 데이터가에에 null 바이트를 포함하지 않는 가정처럼 :
또 다른 옵션 대신
HttpSendRequestEx()
을 사용하는 것입니다
#define DEFAULT_USERAGENT "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
#define MY_HOST "192.168.1.101"
#define ALT_HTTP_PORT 8080
#define METHOD_POST "POST"
#include <vector>
#include <memory>
struct FileCloser
{
typedef HANDLE pointer;
void operator()(HANDLE h)
{
if (h != INVALID_HANDLE_VALUE)
CloseHandle(h);
}
};
struct InetCloser
{
typedef HINTERNET pointer;
void operator()(HINTERNET h)
{
if (h != NULL)
InternetCloseHandle(h);
}
};
void UploadFile()
{
const char *szHeaders = "Content-Type: multipart/form-data; boundary=----974767299852498929531610575";
const char *szContent = "------974767299852498929531610575\r\nContent-Disposition: form-data; name=\"file\"; filename=\"main.cpp\"\r\nContent-Type: application/octet-stream\r\n\r\n";
const char *szEndData = "\r\n------974767299852498929531610575--\r\n";
std::unique_ptr<HANDLE, FileCloser> hIn(CreateFile("main.cpp", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL));
if (hIn.get() == INVALID_HANDLE_VALUE)
{
std::cerr << "CreateFile Error" << std::endl;
return;
}
DWORD dwFileSize = GetFileSize(hIn.get(), NULL);
if (dwFileSize == INVALID_FILE_SIZE)
{
std::cerr << "GetFileSize Error" << std::endl;
return;
}
size_t sContentSize = strlen(szContent);
size_t sEndDataSize = strlen(szEndData);
std::vector<char> vBuffer(sContentSize + dwFileSize + sEndDataSize);
char *szData = &vBuffer[0];
memcpy(szData, szContent, sContentSize);
szData += sContentSize;
DWORD dw = 0, dwBytes;
while (dw < dwFileSize)
{
if (!ReadFile(hIn.get(), szData, dwFileSize-dw, &dwBytes, NULL))
{
std::cerr << "ReadFile Error" << std::endl;
return;
}
szData += dwBytes;
dw += dwBytes;
}
hIn.reset();
memcpy(szData, szEndData, sEndDataSize);
std::unique_ptr<HINTERNET, InetCloser> io(InternetOpen(DEFAULT_USERAGENT, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0));
if (io.get() == NULL)
{
std::cerr << "InternetOpen Error" << std::endl;
return;
}
std::unique_ptr<HINTERNET, InetCloser> ic(InternetConnect(io.get(), MY_HOST, ALT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0));
if (ic.get() == NULL)
{
std::cerr << "InternetConnect Error" << std::endl;
return;
}
std::unique_ptr<HINTERNET, InetCloser> hreq(HttpOpenRequest(ic.get(), METHOD_POST, "/upload", NULL, NULL, NULL, 0, 0));
if (hreq.get() == NULL)
{
std::cerr << "HttpOpenRequest Error" << std::endl;
return;
}
if (!HttpSendRequest(hreq.get(), szHeaders, -1, &vBuffer[0], vBuffer.size()))
std::cerr << "HttpSendRequest Error" << std::endl;
}
, 그래서 루프 내에서 InternetWriteFile()
을 사용하여 각 루프 반복에서 청크로 파일을 읽고 + 전송할 수 있습니다. 그런 식으로, 당신은 보내기 전에 메모리에 전체 파일을 읽을 필요가 없습니다 :
#define DEFAULT_USERAGENT "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
#define MY_HOST "192.168.1.101"
#define ALT_HTTP_PORT 8080
#define METHOD_POST "POST"
#define BUFSIZE 1024
#include <memory>
#include <algorithm>
struct FileCloser
{
typedef HANDLE pointer;
void operator()(HANDLE h)
{
if (h != INVALID_HANDLE_VALUE)
CloseHandle(h);
}
};
struct InetCloser
{
typedef HINTERNET pointer;
void operator()(HINTERNET h)
{
if (h != NULL)
InternetCloseHandle(h);
}
};
bool WriteToInternet(HINTERNET hInet, const void *Data, DWORD DataSize)
{
const BYTE *pData = (const BYTE *) Data;
DWORD dwBytes;
while (DataSize > 0)
{
if (!InternetWriteFile(hInet, pData, DataSize, &dwBytes))
return false;
pData += dwBytes;
DataSize -= dwBytes;
}
return true;
}
void UploadFile()
{
const char *szHeaders = "Content-Type: multipart/form-data; boundary=----974767299852498929531610575";
const char *szContent = "------974767299852498929531610575\r\nContent-Disposition: form-data; name=\"file\"; filename=\"main.cpp\"\r\nContent-Type: application/octet-stream\r\n\r\n";
const char *szEndData = "\r\n------974767299852498929531610575--\r\n";
std::unique_ptr<HANDLE, FileCloser> hIn(CreateFile("main.cpp", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL));
if (hIn.get() == INVALID_HANDLE_VALUE)
{
std::cerr << "CreateFile Error" << std::endl;
return;
}
DWORD dwFileSize = GetFileSize(hIn.get(), NULL);
if (dwFileSize == INVALID_FILE_SIZE)
{
std::cerr << "GetFileSize Error" << std::endl;
return;
}
std::unique_ptr<HINTERNET, InetCloser> io(InternetOpen(DEFAULT_USERAGENT, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0));
if (io.get() == NULL)
{
std::cerr << "InternetOpen Error" << std::endl;
return;
}
std::unique_ptr<HINTERNET, InetCloser> ic(InternetConnect(io.get(), MY_HOST, ALT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0));
if (ic.get() == NULL)
{
std::cerr << "InternetConnect Error" << std::endl;
return;
}
std::unique_ptr<HINTERNET, InetCloser> hreq(HttpOpenRequest(ic.get(), METHOD_POST, "/upload", NULL, NULL, NULL, 0, 0));
if (hreq.get() == NULL)
{
std::cerr << "HttpOpenRequest Error" << std::endl;
return;
}
if (!HttpAddRequestHeaders(hreq.get(), szHeaders, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD))
{
std::cerr << "HttpAddRequestHeaders Error" << std::endl;
return;
}
size_t sContentSize = strlen(szContent);
size_t sEndDataSize = strlen(szEndData);
INTERNET_BUFFERS bufferIn = {};
bufferIn.dwStructSize = sizeof(INTERNET_BUFFERS);
bufferIn.dwBufferTotal = sContentSize + dwFileSize + sEndDataSize;
if (!HttpSendRequestEx(hreq.get(), &bufferIn, NULL, HSR_INITIATE, 0))
{
std::cerr << "HttpSendRequestEx Error" << std::endl;
return;
}
if (!WriteToInternet(hreq.get(), szContent, sContentSize)))
{
std::cerr << "InternetWriteFile Error" << std::endl;
return;
}
char szData[BUFSIZE];
DWORD dw = 0, dwBytes;
while (dw < dwFileSize)
{
if (!ReadFile(hIn.get(), szData, std::min(dwFileSize-dw, sizeof(szData)), &dwBytes, NULL))
{
std::cerr << "ReadFile Error" << std::endl;
return;
}
if (!WriteToInternet(hreq.get(), szData, dwBytes))
{
std::cerr << "InternetWriteFile Error" << std::endl;
return;
}
dw += dwBytes;
}
if (!WriteToInternet(hreq.get(), szEndData, sEndDataSize))
{
std::cerr << "InternetWriteFile Error" << std::endl;
return;
}
if (!HttpEndRequest(hreq.get(), NULL, HSR_INITIATE, 0))
std::cerr << "HttpEndRequest Error" << std::endl;
}
당신이 szContent 및 szEndData를 다시 주실 래요, 그래서 잘 이해할 수 있고, 당신에게 –
@YeniiCeri 감사합니다 : 당신이 정확히 무엇을 이해하지 못하는 ? 'Content-Type' 헤더의 '경계'에 무엇을 지정 하든지 콘텐츠 데이터의 각 경계선 앞에'--'를두기 만하면됩니다. –