https://github.com/simple-uploader/Uploader
上传
simple-uploader.js(也称 Uploader) 是一个上传库,支持多并发上传,文件夹、拖拽、可暂停继续、秒传、分块上传、出错自动重传、手工重传、进度、剩余时间、上传速度等特性;该上传库依赖 HTML5 File API。
由于是分块上传,所以依赖文件的分块 API,所以受限于此浏览器支持程度为:Firefox 4+, Chrome 11+, Safari 6+ and Internet Explorer 10+。
样例分析
默认提供了一个 Node.js 的示例,放在 samples/ 目录下。
在Samples/Node.js目录下,有一个官方的样例。执行如下命令可以运行样例:
cd samples/Node.js[图片上传中...(image.png-38f66f-1586352228338-0)]
-
node app.js
通过http://localhost:3000访问网站
测试上传
异常分析
在uploader-node.js文件中 $.post 函数下添加代码查看文件下载到哪里去了
var files = req.files;
console.log("files",files);
可以看到文件分段后被下载到了c盘用户appdata的temp目录下。
getChunkFilename得到的路径没有问题:
path: D:\——\Uploader-develop\samples\Node.js\tmp\uploader-4703-MyFirstTweenstweens.1
修改fs.rename函数,增加回调函数参数err,输出。
{
errno: -4037,
code: 'EXDEV',
syscall: 'rename',
path: 'C:\\Users\\***\\AppData\\Local\\Temp\\sNHfBf_MilUG1FOxWiX6ozOp.tweens',
dest: 'D:\\***\\Uploader-develop\\samples\\Node.js\\tmp\\uploader-4703-MyFirstTweenstweens.1'
}
错误: code: 'EXDEV',
在app.js文件头提示了:
process.env.TMPDIR = 'tmp';
// to avoid the EXDEV rename error, see http://stackoverflow.com/q/21071303/76173
修改process.env.TMPDIR的方法没成功,但是在stackoverflow的答复中找到了如下方法:
A cleaner solution is to use the
npm mv
module instead offs.rename()
. See https://www.npmjs.com/package/mv
安装
npm i mv
使用方法:
var mv = require('mv');
mv('source/file', 'dest/file', function(err) {
// done. it tried fs.rename first, and then falls back to
// piping the source file to the dest file and then unlinking
// the source file.
});
或
mv('source/dir', 'dest/a/b/c/dir', {mkdirp: true}, function(err) {
// done. it first created all the necessary directories, and then
// tried fs.rename, then falls back to using ncp to copy the dir
// to dest and then rimraf to remove the source dir
});
修改uploader-node.js文件中fs.rename的那行代码,修改为
mv(files[$.fileParameterName].path, chunkFilename,{mkdirp: true}, function(err){
//To Do
});
测试好用。
下载
uploader-node.js文件中通过identifier作为文件的唯一标识。
客户端通过向/download/:identifier请求下载标识identifier的文件。
uploader-node.js中$.write函数使用了fs.createReadStream创造了可读流将identifierd对应的文件读取。
并使用pipe函数绑定response,这样通过可读流读取的信息都会传递给response
在向response输出文本信息之前,通过response.set文件头将文件的基本信息返回客户端
writableStream.set({ 'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename='+file_list[identifier].filename,
'Content-Length': file_list[identifier].size});