如何使用multipartform-data格式上传文件

如何使用multipartform-data格式上传文件,第1张

在网络编程过程中需要向服务器上传文件。Multipart/form-data是上传文件的一种方式。

Multipart/form-data其实就是浏览器用表单上传文件的方式。最常见的情境是:在写邮件时,向邮件后添加附件,附件通常使用表单添加,也就是用multipart/form-data格式上传到服务器。

表单形式上传附件

具体的步骤是怎样的呢?

首先,客户端和服务器建立连接(TCP协议)。

第二,客户端可以向服务器端发送数据。因为上传文件实质上也是向服务器端发送请求。

第三,客户端按照符合“multipart/form-data”的格式向服务器端发送数据。

既然Multipart/form-data格式就是浏览器用表单提交数据的格式,我们就来看看文件经过浏览器编码后是什么样子。

点击“Browse…”分别选择“unknowgif”和“unknow1gif”文件,点击“submit”按纽后,文件将被上传到服务器。

下面是服务器收到的数据:

服务器收到的数据

这是一个POST请求。所以数据是放在请求体内,而不是请求头内。

这行指出这个请求是“multipart/form-data”格式的,且“boundary”是 “---------------------------7db15a14291cce”这个字符串。

不难想象,“boundary”是用来隔开表单中不同部分数据的。例子中的表单就有 2 部分数据,用“boundary”隔开。“boundary”一般由系统随机产生,但也可以简单的用“-------------”来代替。

实际上,每部分数据的开头都是由"--" + boundary开始,而不是由 boundary 开始。仔细看才能发现下面的开头这段字符串实际上要比 boundary 多了个 “--”

紧接着 boundary 的是该部分数据的描述。

接下来才是数据。

“GIF”gif格式的文件头,可见,unknow1gif确实是gif格式。

在请求的最后,则是 "--" + boundary + "--" 表明表单的结束。

需要注意的是,在html协议中,用 “\r\n” 换行,而不是 “\n”。

下面的代码片断演示如何构造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, wstrHeaderc_str(), DWORD(wstrHeadersize()), 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-data; name=\"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 = straMultipartFirstsize() + nPicFileLen + straMultipartIntersize() + straMultipartEndsize();

// Allocate the buffer to temporary store the data to send

PCHAR pchSendBuf = new CHAR[cSendBufLen];

memcpy(pchSendBuf, straMultipartFirstc_str(), straMultipartFirstsize());

memcpy(pchSendBuf + straMultipartFirstsize(), (const char )pchPicFileBuf, nPicFileLen);

memcpy(pchSendBuf + straMultipartFirstsize() + nPicFileLen, straMultipartInterc_str(), straMultipartIntersize());

memcpy(pchSendBuf + straMultipartFirstsize() + nPicFileLen + straMultipartIntersize(), straMultipartEndc_str(), straMultipartEndsize());

//

// send the request data

//

HttpSendRequest(m_hRequest, NULL, 0, (LPVOID)pchSendBuf, cSendBufLen)

在Content-Type: image/jpeg这一行的下面就是的数据。

通过分割字符串或者字节集,将这一行下面的内容与边界——即下一个 ------WebKitFormBoundary48UAMjkvxyyD2ptz 或EOF之间的内容取出,单独写入一个文件,就可以得到文件。

其实易语言不大适合在网页服务器用,因为它的使用真的不算方便。

//本地上传代码Files item = fis as Files;

WebClient wc = new WebClient();

string url = stringFormat("{0}Overwrite=true&Path={1}", "服务器上传地址", itemPath);

 wcUploadFile(url, "POST", itemPath);

 //服务器接收

 string ServerSrc = contextServerMapPath("~/DownLogin/");

        foreach (string filekey in contextRequestFiles)

        {

            HttpPostedFile file = contextRequestFiles[filekey];

            string FilePath = PathCombine(ServerSrc, fileFileName);

            if (FileExists(FilePath))

            {

                if (ConvertToBoolean(contextRequest["overwrite"]))

                {

                    FileDelete(FilePath);

                }

                else

                    continue;

            }

            fileSaveAs(FilePath);

        }

http://1921681212:8011/pd/upload/fileUploaddo;

这个是服务器地址,你要上传的地方。。

理论上是需要一个服务器接收你上传的的!

他这个demo中的url是本地的,目测是写demo的人自己写的用来测试的地址

传统的做法,我们可以在form表单中插入多个inputtype=file,这样用户点击提交 表单 action直接传给服务器,服务端可以拿到file的数组,里面就是用户上传的文件集。

随着浏览器的发展和前端框架的出现,未来的代码将是前后端完全分离的时代,这样,我们的表单将不会再直接通过action和服务器交互,而是需要在js代码中实现文件上传。下面介绍两种多文件上传。

第一种:把从前端页面获取的文件存储在一个数组里,当用户需要提交文件的时候,我们就去便利数组,一个一个上传文件,这样做用户的体验是多文件上传,但是实质是文件一个一个上传的,不足之处是每次上传都是一次POST请求。

第二种:使用formdata上传文件,formdata可以允许我们在js代码里面封装form表单数据,然后我们就可在js中模拟表单提交的过程,从而实现一次POST上传多个文件。

上图中:new FormData() 为实例化一个formdata对象,oMyFormappend("XXX", XXX) 为向该表单对象中添加数据。uploaderqueue为文件数组。

6

上传的结果打印出来如图所示,这样我们就实现了一次POST上传多个文件。

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » 如何使用multipartform-data格式上传文件

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情