檔案傳輸方式
紀錄如何上傳與下載檔案
Browser上傳資料到Server
Server side
使用Express and Multer模組(Multer是改良Busbuy模組,儲存檔案方式是用Streaming)
var express = require('express');
var multer = require('multer');
var app = express();
var storage = multer.diskStorage({
destination: function(req, file, cb){
cb(null, '')
},
filename: function(req, file, cb){
cb(null,file.fieldname)
}
})
var upload = multer({storage: storage}).single('profile');
app.post('/',function(req, res){
upload(req, res, function(err){
console.log(req.body);
console.log(req.file);
if(err){
console.log(err);
}else{
res.status(201).json("success");
}
})
})
app.listen(8080);
Browser side
主要是透過XMLHttpRequest傳送資料,當然也可以用JQuery的AJAX
要注意的地方在於 官方文件說要使用FormData封裝檔案與資料傳輸。
另外我有加入了進度追蹤,詳細介紹請參考此連結。
<html>
<head>
</head>
<body>
<form id="myform" name="myform" enctype='multipart/form-data'>
<input type="file" name="profile">
<input type="submit">
</form>
<script type="text/javascript">
//This is for upload File
function uploadFiles(url, files) {
var formData = new FormData();
for (var i = 0, file; file = files[i]; ++i) {
formData.append('profile', file);
}
formData.append('test', 'hello world');
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function(e) {
console.log(e);
};
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
console.log((e.loaded / e.total) * 100);
}
}
xhr.send(formData);
}
document.querySelector('input[type="file"]').addEventListener('change',function(e) {
console.log(e);
uploadFiles('http://127.0.0.1:8080/', this.files);
console.log("happen");
}, false);
</script>
</body>
下載圖片
Server Side
這邊要注意的是"不能使用同步的方式讀取資料讀取-->造成性能低落"、"使用steam方式傳送資料->不然的話檔案太大,會很快吃光記憶體"。
根據這兩個原則以及此參考連結,實現以下作法
app.get('/profile', function(req, response){
var filePath = path.join(__dirname, 'profile.png');
console.log(filePath);
var stat = fs.statSync(filePath);
response.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': stat.size
});
var readStream = fs.createReadStream(filePath);
readStream.on('data', function(data) {
var flushed = response.write(data);
console.log(data);
// Pause the read stream when the write stream gets saturated
if(!flushed)
readStream.pause();
});
response.on('drain', function() {
// Resume the read stream when the write stream gets hungry
readStream.resume();
});
readStream.on('end', function() {
console.log('end');
response.end();
});
});
Browser side
同樣使用XHR,這邊值得注意的是reponse type設為Blob,後來查發現Blob就是Binary large of Object,通常是指照片或是影音檔;瀏覽器操作Blob可以參考此連結
document.getElementById('downloadImg').addEventListener('click',function(e){
window.URL = window.URL || window.webkitURL; // Take care of vendor prefixes.
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/profile', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
var img = document.getElementById('profileImg');
img.onload = function(e) {
//這行會讓照片無法下載,但依然可以顯示,詳見連結
window.URL.revokeObjectURL(img.src);
};
img.src = window.URL.createObjectURL(blob);
document.body.appendChild(img);
}
};
xhr.send();
});
*如果想要直接下載檔案到電腦,可以用 response.download(your_file_path),瀏覽器會自動跳出下載的對話筐。