利用Ajax無刷新上傳文件到Node.js服務器

jopen 9年前發布 | 92K 次閱讀 Node.js Node.js 開發

最近做一個垂直社區項目,圖片上傳是現如今社區的標配,何況面向的還是女性用戶。后端使用Node.js,圖片上傳必然是要不刷新不用iframe了。順便,也測試了一下Coding.net的“演示”功能,的確是方便免費夠用,代碼傳上去基本零配置就可以跑起來了。這篇文章涉及的代碼托管在Coding上,最終的例子也是運行在Coding的免費服務器上。

協議與結構

整個上傳采用RFC1867協議,即基于HTML表單的文件上傳協議。借助這個協議,為表單增加enctype="multipart/form-data",再使用type為file的input控制來選擇文件,然后便可用POST方法上傳文件。

文件上傳時會分段提交,借助Connect的connect-multiparty模塊,即可接收各段組合整理為文件,并將文件存到臨時目錄,我們可再編寫其它代碼來處理文件。本例中,我們會把文件復制到public目錄,以提供web訪問。

整個示例程序包括以下幾部分:

  • HTML表單,負責文件的選擇
  • JavaScript組織表單數據,執行上傳
  • Node.js接受上傳的文件,并負責文件的移動和組織

示例程序的代碼托管在Coding上的Node.js-Ajax-Upload-File,在線演示地址為node-js-ajax-upload-file.codingapp.com

下面開工。

HTML表單組織

表單很簡單,就一個文件選擇的控件。當type為file的input控件除了常規屬性,還包括一個accept屬性,用于定義可以選擇的文件類型。

HTML中包括一個表單,一個提交按鈕,和一個顯示成功上傳到服務器的圖片的控件,主要代碼如下:

<form class = "form-horizontal" enctype='multipart/form-data' method='post' action='javascript:;' role = "form" id = "frmUploadFile">
<div class = "form-group">
<label class = "control-label col-sm-2">上傳選擇</label>
<div class = "col-sm-4">
<input type = "file" name = "files" class = "form-control" />
</div>
</div>
<div class = "form-group">
<div class = "col-sm-offset-2 col-sm-4">
<button class = "btn btn-primary" onClick = "uploadFile()">上傳</button>
<span class = "help-inline" id = "spanMessage">選擇文件,并上傳</span>
</div>
</div>
</form>
<div class = "row" style = "text-align: center">
<img id = "imgShow" />
</div>


完整代碼請查看public/index.html

Ajax執行上傳

瀏覽器端的JavaScript會將表單中的數據格式化,再以POST方法上傳文件,為了簡便,使用了jQuery庫來操作,具體代碼比較簡單,上傳文件,然后根據服務器端的返回判定上傳是否成功,如果成功,則顯示圖片。

代碼包裝為自定義的函數,由“發送”按鈕的單擊事件調用,代碼如下:

function uploadFile(){
var formData = new FormData($("#frmUploadFile")[0]);
$.ajax({
url: '/upload',
type: 'POST',
data: formData,
async: false,
cache: false,
contentType: false,
processData: false,
success: function(data){
if(200 === data.code) {
$("#imgShow").attr('src', data.msg.url);
$("#spanMessage").html("上傳成功");
} else {
$("#spanMessage").html("上傳失敗");
}
console.log('imgUploader upload success, data:', data);
},
error: function(){
$("#spanMessage").html("與服務器通信發生錯誤");
}
});
}


具體請參見文件pubilc/demo.js

Node.js接收文件

通過POST接收到的文件,由connect-multiparty負責重新組織為文件,并存儲到臨時文件夾中,Linux默認為/tmp目錄,然后再將文件信息放到req.files對象中,對象中按input的name屬性來組織文件列表,我們上面的表單中的input控件name為files,所以文件的信息便存儲在req.files.files中。通過它可獲取文件的存儲位置和文件名等信息。

整個服務器端的代碼很簡單,連同注釋不過20多行,其中處理請求部分的代碼如下:

var multipart = require('connect-multiparty');
app.post('/upload', multipart(), function(req, res){
//get filename
var filename = req.files.files.originalFilename || path.basename(req.files.files.ws.path);
//copy file to a public directory
var targetPath = path.dirname(__filename) + '/public/' + filename;
//copy file
fs.createReadStream(req.files.files.ws.path).pipe(fs.createWriteStream(targetPath));
//return file url
res.json({code: 200, msg: {url: 'http://' + req.headers.host + '/' + filename}});
});


完整代碼請參閱app.js

示例程序的運行

如果系統中已經安裝了git,則可以用下面的命令克隆:

                   
1
                   
$ git clone https://coding.net/Stiekel/Node.js-Ajax-Upload-File.git

也可以下載zip包,程序中的前端包都使用的是百度的公開庫,后端代碼使用npm管理,進入應用目錄,執行如下的命令安裝:

                   
1
                   
$ npm install

然后執行如下的命令可以啟動應用:

                   
1
                   
$ node app.js

再通過瀏覽器訪問http://ip:3000/即可。注意,上傳的文件會保存在/tmp和public兩個目錄中。

來自:http://chensd.com/2015-01/Node-js-Ajax-Upload-File.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!