node.js分片上传文件
前端 :
<html> <head>
<title>分片上传文件</title>
</head> <body>
<div class="hei-bg" style="display:block;">
<div class="user-info" style="display:block;">
<div class="tc">请上传大文件</div>
<div class="user-pic picw320">
<input id="uppic" type="file">
</div>
<div id="jd" class="jdb">进度</div> <div>
<input type="button" value="确定" id="userbtn" class="bg-main tc userbtn">
</div>
</div>
</div>
</body>
<script src="/javascripts/jquery.min.js"></script>
<script>
$(function () {
$('#userbtn').on('click', async function () {
var d1 = new Date();
let file = $("#uppic")[0].files[0], //上传文件主体
name = file.name, //文件名
size = file.size, //总大小
succeed = 0, //当前上传数
shardSize = 1 * 1024 * 1024, //以1MB为一个分片
shardCount = Math.ceil(size / shardSize); //总片数 let attr = [];
try {
for (let item = 0; item < shardCount; ++item) {
await fn(item); //同步
// attr.push(fn(item)); //异步
}
await Promise.all(attr); //异步 $('.jdb').append(' 上传成功');
var d2 = new Date();
console.log(parseInt(d2 - d1) / 1000);
} catch (err) {
$('.jdb').html(err);
console.log(err);
} function fn(item) {
return new Promise((resolve, reject) => {
var i = item;
var start = i * shardSize, //当前分片开始下标
end = Math.min(size, start + shardSize); //结束下标 //构造一个表单,FormData是HTML5新增的
var form = new FormData();
form.append("data", file.slice(start, end)); //slice方法用于切出文件的一部分
form.append("name", name); //文件名字
form.append("total", shardCount); //总片数
form.append("index", i + 1); //当前片数
//Ajax提交 $.ajax({
url: "/sliceUpload",
type: "POST",
data: form,
timeout: 120 * 1000,
async: false, //同步
processData: false, //很重要,告诉jquery不要对form进行处理
contentType: false, //很重要,指定为false才能形成正确的Content-Type
success: function (data) {
++succeed;
if (typeof (data) == 'string') {
try {
data = JSON.parse(data);
console.log(data.msg);
} catch (e) {
console.log(data);
}
}
//生成当前进度百分比
var jd = `${Math.round(succeed / shardCount * 100)}%`;
$('.jdb').html(jd);
/*如果是线上,去掉定时,直接callback(),
这样写是为方便,本地测试看到进度条变化
因为本地做上传测试是秒传,没有时间等待*/
setTimeout(resolve, 50);
}
});
})
}
});
});
</script> </html>
服务器端:
async function sliceUpload(req, res) {
var fs = require('fs');
var multiparty = require('multiparty'); //文件上传模块
var form = new multiparty.Form(); //新建表单
//设置编辑
form.encoding = 'utf-8';
//设置文件存储路径
form.uploadDir = "temp/"; // "Uploads/";
//设置单文件大小限制
// form.maxFilesSize = 200 * 1024 * 1024;
/*form.parse表单解析函数,fields是生成数组用获传过参数,files是bolb文件名称和路径*/
try {
let [fields, files] = await new Promise((resolve, reject) => {
form.parse(req, (err, fields, files) => {
if (err) reject('test err');
resolve([fields, files]);
})
})
files = files['data'][0]; //获取bolb文件
var index = fields['index'][0]; //当前片数
var total = fields['total'][0]; //总片数
var name = fields['name'][0]; //文件名称
var url = 'temp/' + name + index; //临时bolb文件新名字
fs.renameSync(files.path, url); //修改临时文件名字
var pathname = 'Uploads/' + name; //上传文件存放位置和名称
if (index == total) { //当最后一个分片上传成功,进行合并
// 检查文件是存在,如果存在,重新设置名称
let NonExist = await new Promise((resolve, reject) => {
fs.access(pathname, fs.F_OK, (err) => {
resolve(err);
});
})
if (!NonExist) {
var myDate = Date.now();
pathname = 'Uploads/' + myDate + name;
}
logs.info('上传文件:' + pathname);
/*进行合并文件,先创建可写流,再把所有BOLB文件读出来,
流入可写流,生成文件
fs.createWriteStream创建可写流
aname是存放所有生成bolb文件路径数组:
['Uploads/3G.rar1','Uploads/3G.rar2',...]
*/
var writeStream = fs.createWriteStream(pathname);
var aname = [];
for (let i = 1; i <= total; i++) {
let url = 'temp/' + name + i;
let data = await new Promise(function (resolve, reject) {
fs.readFile(url, function (error, data) {
if (error) reject(error);
resolve(data);
});
});
//把数据写入流里
writeStream.write(data);
//删除生成临时bolb文件
fs.unlink(url, () => {});
}
writeStream.end();
//返回给客服端,上传成功
var data = JSON.stringify({
'code': 0,
'msg': '上传成功'
});
res.send(data); //返回数据
} else { //还没有上传文件,请继续上传
var data = JSON.stringify({
'code': 1,
'msg': '继续上传'
});
res.send(data); //返回数据
}
} catch (e) {
logs.info(e);
res.send(e); //返回数据
}
}
node.js分片上传文件的更多相关文章
- Node.js:上传文件,服务端如何获取文件上传进度
内容概述 multer是常用的Express文件上传中间件.服务端如何获取文件上传的进度,是使用的过程中,很常见的一个问题.在SF上也有同学问了类似问题<nodejs multer有没有查看文件 ...
- Node.js——异步上传文件
前台代码 submit() { var file = this.$refs.fileUpload.files[0]; var formData = new FormData(); formData.a ...
- 科普文:Node.js 如何上传文件到后端服务【转】
原文链接 https://www.yuque.com/egg/nodejs/httpclient-upload 背景 互联网时代,无数服务是基于 HTTP 协议进行通信的. 除了常见的 前端浏览器 - ...
- js能否上传文件夹
文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...
- 利用ajaxfileupload.js异步上传文件
1.引入ajaxfileupload.js 2.html代码 <input type="file" id="enclosure" name="e ...
- js获取上传文件内容(未完待续)
js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...
- django实现分片上传文件
目标:利用django实现上传文件功能 1,先设置路由系统 urls.py from django.conf.urls import url,include from django.contrib i ...
- Atitit.js获取上传文件全路径
Atitit.js获取上传文件全路径 1. 默认的value只能获取文件名..安全原因.. 1 2. Firefox浏览器的读取 1 3. Html5 的file api 2 4. 解决方法::使用a ...
- js获取上传文件内容
js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...
随机推荐
- php代码审计3审计sql注入漏洞
SQL注入攻击(sql injection)被广泛用于非法获取网站控制权,在设计程序时,忽略或过度任性用户的输入,从而使数据库受到攻击,可能导致数据被窃取,更改,删除以及导致服务器被嵌入后门程序等 s ...
- python基础之内置函数(一)
内建函数都在 _builtins_ 里面 (1)abs() 取绝对值 adb(-10) 10 (2)bool()将参数转换成布尔型,返回值是True或False 参数是数字时,0返回False,其他任 ...
- Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解)
不多说,直接上干货! 一.自定义拦截器类型必须是:类全名$内部类名,其实就是内部类名称 如:zhouls.bigdata.MySearchAndReplaceInterceptor$Builder 二 ...
- update 多表链接
update Aset A.shl = A.shl - B.shl from retmxls A,daysphz Bwhere A.spid = B.spid and A.fdbs = B.fdbs ...
- 利用EFCore 封装Repository(可扩展不同数据的sql操作)
本篇是对EFCore 进行下封装并实现基本的增删改查的同步异步方法及针对不同数据库的批量插入.sql语句直接操作数据库: 一. 先定义基础仓储接口IRepository public interfac ...
- 【语义分割】PSPNet中PSP模块的pytorch实现
github地址:https://github.com/Lextal/pspnet-pytorch/blob/master/pspnet.py PSP模块示意图如下 代码如下 class PSPMod ...
- JavaWeb学习笔记(五)—— request
一.request概述 request是Servlet.service()方法的一个参数,类型为javax.servlet.http.HttpServletRequest.在客户端发出每个请求时,服务 ...
- python学习之路---day12
生成器和生成器表达式一:生成器 生成器实质上就是迭代器. 三种方式获取生成器: 01:通过生成器函数 02:通过各种推导式实现生成器 03:通过数据的转换也可以获取生成器 eg:普通函数 def fu ...
- 使用Git向GitHub上上传代码
参考:http://www.cnblogs.com/yxhblogs/p/6130995.html 如果遇到[git无法pull仓库refusing to merge unrelated histor ...
- 洛谷 P1272 重建道路
题目链接 题解 树形dp \(f_{i, j}\)表示以\(i\)为根的子树切出联通块大小为\(j\)的最小答案 显然\(f[i][1]\)为与\(i\)连的边数 设\(v\)是\(u\)的儿子 那么 ...