學習了nodejs,就想實現一下有進度條的文件上傳,html
在作這個功能的時候遇到的問題前端
用普通的ajax沒法實現文件上傳,只能post,get,一些json,string字符串;node
想要上傳文件或者圖片,能夠添加form上傳;注意須要在form上添加 標示 enctype="multipart/form-data"ajax
缺點,這樣會倒置頁面的刷新;很糟糕有沒有json
還能夠在頁面中添加一個ifame,將表單提交到ifame中,不過,一據說有iframe就有點糟心有沒有;後端
因而就有了下面的東西;
請自動忽略沒有樣式(只是爲了實現功能)這個梗,啊哈哈;閉包
好了廢話少說直接上代碼app
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> .progressBar{ width: 150px; height: 15px; border: 1px solid red; /*display: none;*/ border-radius: 5px; } .bar { width: 0; height: 100%; background: #08d09a; border-radius: 5px; line-height: 0; margin: 0; } </style> </head> <body> <button id="submit">提交</button> <input type="file" name="file" id="fileInputElement"/> <div class="progressBar" style="display: none;"> <p class="bar"></p> </div> <script> var btn = document.getElementById('submit'); var fileInputElement = document.getElementById('fileInputElement'); var bar = document.getElementsByClassName('bar')[0]; var progressBar = document.getElementsByClassName('progressBar')[0]; btn.onclick =function(){ progressBar.style.display = 'block'; var oMyForm = new FormData(); oMyForm.append("username", "Groucho"); oMyForm.append("accountnum", 123456); // 數字123456被當即轉換成字符串"123456" // fileInputElement中已經包含了用戶所選擇的文件 oMyForm.append("userfile", fileInputElement.files[0]); var oFileBody = '<a id="a"><b id="b">hey!</b></a>'; // Blob對象包含的文件內容 var oBlob = new Blob([oFileBody], { type: "text/xml"}); var oReq = new XMLHttpRequest(); oReq.open("POST", "/formupload"); // 文件上傳過程的回調 oReq.upload.onprogress = function(e) { console.log((e.loaded/e.total)*100+'%') bar.style.width = (e.loaded/e.total)*100+'%'; } /** * e.loaded 文件已經上傳了的大小 * e.total 文件總大小 e.loaded/e.total)*100+'%' 轉化成比例; */ // 文件上傳完畢的回調 oReq.upload.onloadend = function(e) { console.log('接收完成'+e.loaded+'/'+e.total); setTimeout(function(){ progressBar.style.display = 'none'; bar.style.width = 0; },1000) } oReq.send(oMyForm); } </script> </body> </html>
使用方法dom
經過new FormData 建立一個form提交實例對象;此對象會有append方法,異步
用法 oMyform.append(name,value) name是一個字段,value是對應的值(能夠是字符串,數字,file文件(經過dom.files[0]得到))
var oMyForm = new FormData(); oMyForm.append("username", "Groucho"); oMyForm.append("accountnum", 123456); oMyForm.append("userfile", fileInputElement.files[0]);
注意 onprogress、onloadend、須要經過xhr.upload 調用以下;
oReq.upload.onprogress=function(e){ console.log(e.loaded) console.log(e.total) }; oReq.upload.onloadend=function(e){};
主要用到了formidable模塊
/** * [導出一箇中間件,formupload,用於處理文件上傳;] */ exports.formupload = function(req,res,next){ //console.log(req); var form = new formidable.IncomingForm(); var uploadDir = path.normalize(__dirname+'/'+"../avatar"); form.uploadDir = uploadDir; console.log(uploadDir); form.parse(req, function(err, fields, files) { for(item in files){ (function(){ var oldname = files[item].path; var newname = files[item].name === 'blob' ? oldname+'.xml' : oldname+"."+files[item].name.split('.')[1]; fs.rename(oldname,newname,function(err){ if(err) console.log(err); console.log('修改爲功'); }) })(item); } console.log(util.inspect({fields: fields, files: files})); res.send('2'); });
for 循環中有異步邏輯,致使異步邏輯出現問題;
formidable 的上傳文件路徑用相對路徑會找不到所指定的路徑
能夠用閉包實現,每次傳進到閉包的變量不會受到外界的影響;
用牛逼的__dirname 變量;指向當前文件的絕對路徑;