通过HTTP协议上传文件
生活随笔
收集整理的這篇文章主要介紹了
通过HTTP协议上传文件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
HTTP是很常見的協議,雖然用得很多,但對細節的了解卻是很淺,這回通過向服務端上傳文件信息來理解細節。網絡庫的選擇:1、WinHTTP是windows下常用的庫;2、CURL是廣受喜愛的開源庫。對于我來說,libcurl最大的優點是使用方便,可以把注意力更多的集中到業務層上,提高工作效率,避免重造輪子;缺點是略大(MD編譯有264KB,MT編譯有340KB),不像WinHTTP可以由windows操作系統集成。下邊展示如何使用這兩種網絡庫實現表單POST文件。
一、libcurl
庫下載:http://curl.haxx.se/download.html 庫編譯:把include、lib的代碼拿出來,使用靜態庫,設置預定義宏BUILDING_LIBCURL。 測試工程:設置預定義宏CURL_STATICLIB;添加依賴lib:Ws2_32.lib Wldap32.lib。 ? ? ?主要代碼: void curl_post_cswuyg() {curl_global_init(CURL_GLOBAL_ALL);CURL* hCurl = curl_easy_init();if(hCurl != NULL){//也許有Expect: 100-continue,去掉它curl_slist* pOptionList = NULL;pOptionList = curl_slist_append(pOptionList, "Expect:");curl_easy_setopt(hCurl, CURLOPT_HTTPHEADER, pOptionList);curl_httppost* pFormPost = NULL;curl_httppost* pLastElem = NULL;//上傳文件,指定本地文件完整路徑curl_formadd(&pFormPost, &pLastElem, CURLFORM_COPYNAME, "ufile01", CURLFORM_FILE, "C:\\temp\\upload_test_curl_cswuyg.txt", CURLFORM_CONTENTTYPE, "application/octet-stream", CURLFORM_END);//上傳自定義文件內容的文件,CURLFORM_BUFFER指定服務端文件名//http://curl.haxx.se/libcurl/c/curl_formadd.htmlchar* file_info = "file_info——cswuyg";int record_length = std::string(file_info).length();curl_formadd(&pFormPost, &pLastElem,CURLFORM_COPYNAME, "ufile01",CURLFORM_BUFFER, "cswuyg_test.txt",CURLFORM_BUFFERPTR, file_info,CURLFORM_BUFFERLENGTH, record_length,CURLFORM_END);//不加一個結束的hfs服務端無法寫入文件,一般不存在這種問題,這里加入只是為了測試.//curl_formadd(&pFormPost, &pLastElem, CURLFORM_COPYNAME, "end", CURLFORM_COPYCONTENTS, "end", CURLFORM_END); curl_easy_setopt(hCurl, CURLOPT_HTTPPOST, pFormPost);curl_easy_setopt(hCurl, CURLOPT_URL, "http://127.0.0.1/hfs_up/");CURLcode res = curl_easy_perform(hCurl);if(res != CURLE_OK){std::wcout << "Error" << std::endl;}curl_formfree(pFormPost);curl_easy_cleanup(hCurl);}curl_global_cleanup(); } ?wireshark抓包,127.0.0.1地址無法抓到,網絡上有解決方案。示意圖: 頭域設置分割符: MIME部分:二、WinHTTP
庫:winhttp.lib 主要代碼: void cswuyg_winhttp_post() {HINTERNET hSession = ::WinHttpOpen(L"cswuyg post test/1.0", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, NULL);HINTERNET hConnect = ::WinHttpConnect(hSession, L"127.0.0.1", INTERNET_DEFAULT_HTTP_PORT, 0);if (hConnect == NULL){int i = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;return;}const wchar_t* lpszAcceptedType[] = {L"*/*", NULL};HINTERNET hRequest = ::WinHttpOpenRequest(hConnect, L"POST", L"hfs_up", L"HTTP/1.1", WINHTTP_NO_REFERER, lpszAcceptedType, 0);if (hRequest == NULL){return;}DWORD dwTime = 5000;::WinHttpSetOption(hRequest, WINHTTP_OPTION_CONNECT_TIMEOUT, &dwTime, sizeof(DWORD));std::wstring strHeader = L"Content-Type: multipart/form-data; boundary=--boundary_cswuygtest\r\n";::WinHttpAddRequestHeaders(hRequest, strHeader.c_str(), strHeader.length(), WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);std::string strMIME = "----boundary_cswuygtest\r\n";strMIME += "Content-Disposition: form-data; name=\"ufile01\"; filename=\"upload_test_http_cswuyg.txt\"\r\n";strMIME += "Content-Type:application/octet-stream\r\n\r\n";strMIME += "1\r\n";///////除了這個表單之外,后頭還必須要有另外的表單信息,否則hfs服務端那邊無法寫入文件,這里僅為測試。//strMIME += "----boundary_cswuygtest\r\n" ;//strMIME += "Content-Disposition: form-data; name=\"name\"\r\n\r\n";//strMIME += "temp.txt\r\n";/strMIME += "----boundary_cswuygtest--\r\n";///可以直接寫入//::WinHttpSendRequest(hRequest, strHeader.c_str(), strHeader.length(), (LPVOID)strMIME.c_str(), strMIME.length(), strMIME.length(), 0);//也可以后面分步寫入::WinHttpSendRequest(hRequest, NULL, 0, NULL, 0, strMIME.length(), 0);DWORD dwWritten = 0;while(!strMIME.empty()){::WinHttpWriteData(hRequest, strMIME.c_str(), strMIME.length(), &dwWritten);if (strMIME.length() > dwWritten){strMIME.substr(dwWritten);}else{strMIME = "";}}::WinHttpReceiveResponse(hRequest, NULL);char buf[1024] = { 0 };DWORD dwToRead = 1024;DWORD dwHaveRead = 0;::WinHttpReadData(hRequest, buf, dwToRead, &dwHaveRead);std::cout << buf << std::endl;::WinHttpCloseHandle(hRequest);::WinHttpCloseHandle(hConnect);::WinHttpCloseHandle(hSession); } ?wireshark抓包: 頭域設置: 表單設置:三、總結
這兩個例子用hfs做服務器測試可以發現在上傳文件夾中上傳了文件,代碼都很簡單。測試過程中的最重要的是能盡快的反饋結果,所以能自己搭建一個http服務器很重要,hfs工具,非常簡單便捷。 POST表單最重要的是了解表單的格式。首先要在頭域增加Content-Type說明,如:“content-type:multipart/from-data; boundary=--cswuyg”。然后http body填充的數據要以MIME格式上傳,每部分數據的開頭都是由“--”+boundary開始的,結尾以"--"+boundary+"--"結束。 如果要上傳文件,需要跟服務器約定好格式,譬如上邊例子約定在content-Disposition中有filename鍵的則是上傳文件信息,該片的content為文件數據,這應該是比較通用的約定。 本文所在:http://www.cnblogs.com/cswuyg/p/3185164.html 附上部分資料:MIME:http://baike.baidu.com/view/160611.htm
MIME來源 : Multipurpose Internet Mail Extensions 多用途互聯網郵件擴展。服務器會將它們發送的多媒體數據的類型告訴瀏覽器,而通知手段就是說明該多媒體數據的MIME類型。
GZIP文件:application/x-gzip
任意的二進制數據:application/octet-stream.
普通文本:text/plain
轉載于:https://www.cnblogs.com/cswuyg/p/3185164.html
總結
以上是生活随笔為你收集整理的通过HTTP协议上传文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AS3.0的int uint Numbe
- 下一篇: 编译cscope-15.8a遇到的问题与