背景:原来在项目中使用 flash 实现文件上传,但是现在浏览器默认是禁用 flash 的,需要手动启动,不太方便,所以修改为使用 H5。
前端代码:
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title>文件上传</title> 9 </head> 10 11 <body> 12 <h3>文件上传</h3> 13 <input type="file" name="inputFile" id="" onchange="uploadFile()"> 14 15 <script src="./jquery.min.js"></script> 16 <script> 17 var uploadFile = function (event) { 18 var e = event || window.event; 19 var file = e.target.files[0]; 20 var fileReader = new FileReader(); 21 22 var toBlob = function (a) { 23 return new Blob([a], { 24 type: file.type 25 }); 26 } 27 fileReader.onload = function () { 28 var result = this.result; 29 var blob = new Blob([result], { 30 type: file.type 31 }); 32 var formData = new FormData(); 33 // inputFile: 在 form 表单中是 input 的 name 属性值,此字段 为后台读取数据的字段 34 formData.append('inputFile', blob, file.name); 35 console.log('formData--', formData); 36 $.ajax({ 37 type: "post", 38 url: "http://127.0.0.1:8080/uploadFile", 39 processData: false, 40 contentType: false, 41 data: formData, 42 timeout: 6000, 43 success: function (data) { 44 console.log('upload success') 45 }, 46 error: function (xhr, text) { 47 if (text === 'timeout') { 48 xhr.abort(); 49 } 50 } 51 }); 52 } 53 54 fileReader.readAsArrayBuffer(file); 55 } 56 </script> 57 </body> 58 59 </html>
后台代码:
1 var express = require('express'); 2 var app = express(); 5 var multiparty = require('multiparty'); 3 var util = require('util'); 4 var fs = require('fs'); 5 6 7 app.use(bodyParser.urlencoded({ 8 extended: true, 9 }));19 app.use(function (req, res, next) { 10 11 // Website you wish to allow to connect 12 res.setHeader('Access-Control-Allow-Origin', "*"); 13 14 // Request methods you wish to allow 15 res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); 16 17 // Request headers you wish to allow 18 res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); 19 20 // Set to true if you need the website to include cookies in the requests sent 21 // to the API (e.g. in case you use sessions) 22 // res.setHeader('Access-Control-Allow-Credentials', 'true'); 23 24 // Pass to next layer of middleware 25 next(); 26 }); 27 28 app.post('/uploadFile', function (req, res) { 29 // 生成multiparty对象,并配置上传目标路径 30 var form = new multiparty.Form(); 31 // 设置编辑 32 form.encoding = 'utf-8'; 33 form.parse(req, function (err, fields, files) { 34 var filesTemp = JSON.stringify(files, null, 2); 35 36 if (err) { 37 console.log('parse error:' + err); 38 } else { 39 // console.log('parse files:' + filesTemp); 40 var inputFile = files.inputFile[0]; 41 var uploadedPath = inputFile.path; 42 43 var readStream = fs.createReadStream(uploadedPath); 44 // './src/files/' 文件保存的路径(相对于当前项目文件路径) originalFilename 源文件的名称 45 var writeStream = fs.createWriteStream('./src/files/' + inputFile.originalFilename); 46 readStream.pipe(writeStream); 47 readStream.on("end", function () { 48 // Operation done 49 console.log('Operation done'); 50 }); 51 } 52 53 res.writeHead(200, { 54 'content-type': 'text/plain' 55 }); 56 res.write('received upload: '); 57 res.end(util.inspect({ 58 fields: fields, 59 files: files 60 })); 61 }); 62 }); 63 64 65 var server = app.listen(8080, function () { 66 var host = server.address().address; 67 var port = server.address().port; 68 69 console.log("应用实例,访问地址为 http://%s:%s", host, port); 70 });
注意:
1、使用 fs.rename 重命名文件名时会报错: EXDEV: cross-device link not permitted
2、util.pump() is deprecated. Use readableStream.pipe() instead.