前端ajax上傳文件,圖片,後端nodejs接收文件;

前端ajax上傳文件,圖片,後端nodejs接收文件;

學習了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>

用到了 FormData 類;

使用方法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]);

用到了XMLHttpRequest 的 onprogress 和 onloadend

注意 onprogress、onloadend、須要經過xhr.upload 調用以下;

oReq.upload.onprogress=function(e){
    console.log(e.loaded)
    console.log(e.total)
};
oReq.upload.onloadend=function(e){};

nodejs 後端的處理

主要用到了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 變量;指向當前文件的絕對路徑;

相關文章
相關標籤/搜索