在网络编程过程中需要向服务器上传文件。Multipart/form-data是上传文件的一种方式。
Multipart/form-data其实就是浏览器用表单上传文件的方式。最常见的情境是:在写邮件时,向邮件后添加附件,附件通常使用表单添培罩加,态孝也就是用multipart/form-data格式上传到服务器。
表单形式上传附件
具体的步骤是怎样的呢?
首先,客户端和服务器建立连接(TCP协议)。
第二,客户端可以向服务器端发送数据。因为上传文件实质上也是向服务器端发送请求。
第三,客户端按照符合“multipart/form-data”的格式向服务器端发送数帆中稿据。
Multipart/form-data的格式是怎样的呢?
既然Multipart/form-data格式就是浏览器用表单提交数据的格式,我们就来看看文件经过浏览器编码后是什么样子。
//---------------------------------------
// this is the demo code of using multipart/form-data to upload text and
photos.
// -use WinInet APIs.
//
//
// connection handlers.
//
HRESULT hr
HINTERNET m_hOpen
HINTERNET m_hConnect
HINTERNET m_hRequest
//
// make connection.
//
...
//
// form the content.
//
std::wstring strBoundary = std::wstring(L"------------------")
std::wstring wstrHeader(L"Content-Type: multipart/form-data, boundary=")
wstrHeader += strBoundary
HttpAddRequestHeaders(m_hRequest, wstrHeader.c_str(),
DWORD(wstrHeader.size()), HTTP_ADDREQ_FLAG_ADD)
//
// "std::wstring strPhotoPath" is the name of photo to upload.
//
//
// uploaded photo form-part begin.
//
std::wstring strMultipartFirst(L"--")
strMultipartFirst += strBoundary
strMultipartFirst += L"\r\nContent-Disposition: form-dataname=\"pic\"
filename="
strMultipartFirst += L"\"" + strPhotoPath + L"\""
strMultipartFirst += L"\r\nContent-Type: image/jpeg\r\n\r\n"
//
// "std::wstring strTextContent" is the text to uploaded.
//
//
// uploaded text form-part begin.
//
std::wstring strMultipartInter(L"\r\n--")
strMultipartInter += strBoundary
strMultipartInter += L"\r\nContent-Disposition: form-data
name=\"status\"\r\n\r\n"
std::wstring
wstrPostDataUrlEncode(CEncodeTool::Encode_Url(strTextContent))
// add text content to send.
strMultipartInter += wstrPostDataUrlEncode
std::wstring strMultipartEnd(L"\r\n--")
strMultipartEnd += strBoundary
strMultipartEnd += L"--\r\n"
//
// open photo file.
//
// ws2s(std::wstring)
// -transform "strPhotopath" from unicode to ansi.
std::ifstream *pstdofsPicInput = new std::ifstream
pstdofsPicInput->open((ws2s(strPhotoPath)).c_str(),
std::ios::binary|std::ios::in)
pstdofsPicInput->seekg(0, std::ios::end)
int nFileSize = pstdofsPicInput->tellg()
if(nPicFileLen == 0)
{
return E_ACCESSDENIED
}
char *pchPicFileBuf = NULL
try
{
pchPicFileBuf = new char[nPicFileLen]
}
catch(std::bad_alloc)
{
hr = E_FAIL
}
if(FAILED(hr))
{
return hr
}
pstdofsPicInput->seekg(0, std::ios::beg)
pstdofsPicInput->read(pchPicFileBuf, nPicFileLen)
if(pstdofsPicInput->bad())
{
pstdofsPicInput->close()
hr = E_FAIL
}
delete pstdofsPicInput
if(FAILED(hr))
{
return hr
}
// Calculate the length of data to send.
std::string straMultipartFirst = CEncodeTool::ws2s(strMultipartFirst)
std::string straMultipartInter = CEncodeTool::ws2s(strMultipartInter)
std::string straMultipartEnd = CEncodeTool::ws2s(strMultipartEnd)
int cSendBufLen = straMultipartFirst.size() + nPicFileLen +
straMultipartInter.size() + straMultipartEnd.size()
// Allocate the buffer to temporary store the data to send.
PCHAR pchSendBuf = new CHAR[cSendBufLen]
memcpy(pchSendBuf, straMultipartFirst.c_str(),
straMultipartFirst.size())
memcpy(pchSendBuf + straMultipartFirst.size(), (const char *)pchPicFileBuf,
nPicFileLen)
memcpy(pchSendBuf + straMultipartFirst.size() + nPicFileLen,
straMultipartInter.c_str(), straMultipartInter.size())
memcpy(pchSendBuf + straMultipartFirst.size() + nPicFileLen +
straMultipartInter.size(), straMultipartEnd.c_str(),
straMultipartEnd.size())
//
// send the request data.
//
HttpSendRequest(m_hRequest, NULL, 0, (LPVOID)pchSendBuf, cSendBufLen)
建议你每次打开淘宝助理都要先更新下数据,同步下系统
淘宝助理5的版本系统比较不稳定,经常会出现一些无法解辩棚释的系统性问题
所以,一定要用淘宝助理5的版本的话,一定要养成习惯, *** 作几个步骤就更新同步一次
个人推荐使用旧的版本,淘宝助理4,系统会比较稳定一些
有时候用数据包导入的宝贝,每个宝贝都要稍微修改下桥搜,然后点击确定保存下,
每个宝贝都这样 *** 作,就算不修改,只要每个宝贝都点击下保存敏灶历也会提高上传的成功率
希望可以帮到你,望采纳,有其他问题可以继续提问。。。
BOOL InternetWriteFile(IN HINTERNET hFile,
IN LPCVOID lpBuffer,
IN DWORD dwNumberOfBytesToWrite,
OUT LPDWORD lpdwNumberOfBytesWritten
)
hFile
Valid handle returned from a previous call to FtpOpenFile or an HINTERNET handle sent by HttpSendRequestEx.
lpBuffer
Address of a buffer that contains the data to be written to the file.
dwNumberOfBytesToWrite
Number of bytes to write to the file.
lpdwNumberOfBytesWritten
Address of a variable that receives the number of bytes written to the buffer. InternetWriteFile sets this value to zero before doing any work or error checking.
给个例子:
#include <Windows.h>
#include <WinINet.h>
#include <stdio.h>
BOOL UseHttpSendReqEx(HINTERNET hRequest, DWORD dwPostSize)
#define BUFFSIZE 500
void main( int argc, char **argv )
{
DWORD dwPostSize
if (argc <4)
{
printf("Usage: Bigpost <Size><敏雹庆Server><Path>\n")
printf("<Size>is the number of KB to POST\n")
printf("<Server>is the server to POST to\n")
printf("<Path>is the virtual path to POST to\n")
exit(0)
}
if ( ((dwPostSize = strtoul(argv[1],NULL,10)) == 0) || (dwPostSize >=) )
{
printf("%s is invalid size. Valid sizes are from 1 to 2047999\n",[1])
exit(0)
}
printf( "Test of POSTing %luKB with WinInet\肆昌n", dwPostSize)
dwPostSize *= 1024// Convert KB to bytes
HINTERNET hSession = InternetOpen( "HttpSendRequestEx",,
NULL, NULL, 0)
if(!hSession)
{
printf("Failed to open session\n")
exit(0)
}
HINTERNET hConnect = InternetConnect(hSession, argv[2],,
NULL, NULL, INTERNET_SERVICE_HTTP,NULL, NULL)
if (!hConnect)
printf( "Failed to connect\n"桥握 )
else
{
HINTERNET hRequest = HttpOpenRequest(hConnect, "POST", argv[3],
NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0)
if (!hRequest)
printf( "Failed to open request handle\n" )
else
{
if(UseHttpSendReqEx(hRequest, dwPostSize))
{
char pcBuffer[BUFFSIZE]
DWORD dwBytesRead
printf("\nThe following was returned by the server:\n")
do
{dwBytesRead=0
if(InternetReadFile(hRequest, pcBuffer, BUFFSIZE-1,&dwBytesRead))
{
pcBuffer[dwBytesRead]=0x00// Null-terminate buffer
printf("%s", pcBuffer)
}
else
printf("\nInternetReadFile failed")
}while(dwBytesRead>0)
printf("\n")
}
if (!InternetCloseHandle(hRequest))
printf( "Failed to close Request handle\n" )
}
if(!InternetCloseHandle(hConnect))
printf("Failed to close Connect handle\n")
}
if( InternetCloseHandle( hSession ) == FALSE )
printf( "Failed to close Session handle\n" )
printf( "\nFinished.\n" )
}
BOOL UseHttpSendReqEx(HINTERNET hRequest, DWORD dwPostSize)
{
INTERNET_BUFFERS BufferIn
DWORD dwBytesWritten
int n
BYTE pBuffer[1024]
BOOL bRet
BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS )// Must be set or error will occur
BufferIn.Next = NULL
BufferIn.lpcszHeader = NULL
BufferIn.dwHeadersLength = 0
BufferIn.dwHeadersTotal = 0
BufferIn.lpvBuffer = NULL
BufferIn.dwBufferLength = 0
BufferIn.dwBufferTotal = dwPostSize// This is the only member used other than dwStructSize
BufferIn.dwOffsetLow = 0
BufferIn.dwOffsetHigh = 0
if(!HttpSendRequestEx( hRequest, &BufferIn, NULL, 0, 0))
{
printf( "Error on HttpSendRequestEx %d\n",GetLastError() )
return FALSE
}
FillMemory(pBuffer, 1024, 'D')// Fill buffer with data
bRet=TRUE
for(n=1n<=(int)dwPostSize/1024 &&bRetn++)
{
if(bRet=InternetWriteFile( hRequest, pBuffer, 1024, &dwBytesWritten))
printf( "\r%d bytes sent.", n*1024)
}
if(!bRet)
{
printf( "\nError on InternetWriteFile %lu\n",GetLastError() )
return FALSE
}
if(!HttpEndRequest(hRequest, NULL, 0, 0))
{
printf( "Error on HttpEndRequest %lu \n", GetLastError())
return FALSE
}
return TRUE
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)