重拾cgi——檔案上傳和cgicc
html中上傳檔案,只需要表單裡面放一個input type=file即可,如果要使用ajax非同步上傳(下文基於jquery),就需要注意幾點(以下操作,部分需要基於html5定義的api):
1、頁面上建立一個input元素,type是file。如果一個input需要支援選擇多個檔案,在標籤中增加屬性:multiple=”multiple”。(注意,這需要瀏覽器支援html5,具體文件可以見)
2、獲取這個元素繫結的已上傳檔案:
[cce lang=”javascript”]
var files = document.getElementById(‘xxx’).files;
[/cce]
先獲取元素,通過讀取元素的files屬性,獲取所有已經選擇的檔案。
3、組裝formdata,因為上傳檔案可能會比較大,所以即使支援多選檔案,這裡還是分成不同的請求傳送。
[cce lang=”javascript”]
for(var i=0;i<array.length;i++) {
var file = files[index];
var formData = new FormData();
formData.append(“file”, file);
formData.append(“id”, i+1);
}
[/cce]
這裡將每個檔案單獨組裝成一個formdata,裡面包含檔案內容和一個id。
4、通過jquery發起post請求:
[cce lang=”javascript”]
$.ajax({
type: `POST`,
url: “file/new”,
data: formData,
async: true,
cache: false,
processData: false,
contentType: false,
xhr: function() {
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){
myXhr.upload.addEventListener(`progress`,progressHandlerFunction, false);
}
return myXhr;
},
success: function(data){
if(!data.result) {
progressTag.remove();
$(“#” + index).after($(`<span style=”color:red”>`+data.msg+`</span>`));
}
}
});
[/cce]
其中的xhr部分稍後會提到,這裡還有兩個需要特別注意的地方。首先是processData屬性,必須設定為false,其次是contentType必須設定為false。其他後端不清楚,cgicc在處理檔案上傳(既multipart方式post的時候),必須從http頭中讀取Content-Disposition屬性,只有在jquery裡面設定了前面提到的兩個屬性,才能正確的按照標準協議進行封裝,讓cgicc讀取到正確的內容分隔字串。
5、錦上添花,增加進度條:
[cce lang=”javascript”]
var progressTag = $(“<progress/>”, {
value: 0,
min: 0,
max: file.size
});
$(“#” + index).after(progressTag);
function progressHandlerFunction(evt) {
if (evt.lengthComputable) {
progressTag.attr(“max”, evt.total);
progressTag.attr(“value”, evt.loaded);
}
}
[/cce]
這裡通過jquery動態的增加了一個progress標籤(html5中新增),然後定義了一個handler。之前jquery的ajax函式中看見了,通過獲取原生xhr物件,在upload事件上增加handler函式回撥,在上傳的同時,將具體進度反饋給使用者。當然,如果需要,這裡也可以繫結download事件。
6、cgicc處理檔案:
cgicc處理檔案和普通表單元素類似,唯一的區別是需要通過cgi.getFile函式來獲取,而不是cgi.getElement。
[cce lang=”cpp”]
cgicc::form_iterator idIter = cgi.getElement(“id”);
cgicc::file_iterator fileIter = cgi.getFile(“file”);
if(idIter == cgi.getElements().end())
{
//handle error
}
int id = (int)idIter->getIntegerValue();
if(fileIter == cgi.getFiles().end())
{
//handle error
}
std::ofstream of(boost::lexical_cast<std::string>(id));
fileIter->writeToStream(of);
[/cce]
這裡忽略了錯誤處理,通過獲取表單元素,作為檔名,直接將檔案通過標準庫檔案輸出流ofstream寫到磁碟上。
這樣,就完成了從頁面上選擇檔案,到後臺儲存的簡單流程。
相關文章
- 開源專案之---cgi ( cgicc )
- 單個檔案上傳和批量檔案上傳
- php檔案上傳之多檔案上傳PHP
- 檔案上傳原理和實現
- 檔案上傳和下載功能
- 檔案上傳
- SpringMVC 單檔案上傳與多檔案上傳SpringMVC
- struts檔案上傳,獲取檔名和檔案型別型別
- Java大檔案上傳、分片上傳、多檔案上傳、斷點續傳、上傳檔案minio、分片上傳minio等解決方案Java斷點
- 上傳圖片和檔案出錯!!!
- 檔案上傳之三基於flash的檔案上傳
- 前端大檔案上傳/分片上傳前端
- Flask——檔案上傳Flask
- PHP上傳檔案PHP
- JavaScript 檔案上傳JavaScript
- Git上傳檔案Git
- YII檔案上傳
- 檔案上傳概述
- beego上傳檔案Go
- 上傳檔案流程
- 上傳EXCLE檔案
- PHP 檔案上傳PHP
- 檔案上傳漏洞
- spring cloud feign 檔案上傳和檔案下載SpringCloud
- MVC檔案上傳 - 使用Request.Files上傳多個檔案MVC
- .NET Core 如何上傳檔案及處理大檔案上傳
- git和tormoisegit上傳本地檔案到githubORMGithub
- Django檔案上傳 -- 適用於單一小檔案上傳Django
- Java SE 檔案上傳和檔案下載的底層原理Java
- 上傳檔案的陷阱
- HTTP檔案上傳原理HTTP
- 上傳檔案專題
- PHP 分片上傳檔案PHP
- Java Web 檔案上傳JavaWeb
- WEB漏洞——檔案上傳Web
- Aliyun Oss 上傳檔案
- 使用fileinput上傳檔案
- PHP ftp上傳檔案PHPFTP