前端 :

<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分片上传文件的更多相关文章

  1. Node.js:上传文件,服务端如何获取文件上传进度

    内容概述 multer是常用的Express文件上传中间件.服务端如何获取文件上传的进度,是使用的过程中,很常见的一个问题.在SF上也有同学问了类似问题<nodejs multer有没有查看文件 ...

  2. Node.js——异步上传文件

    前台代码 submit() { var file = this.$refs.fileUpload.files[0]; var formData = new FormData(); formData.a ...

  3. 科普文:Node.js 如何上传文件到后端服务【转】

    原文链接 https://www.yuque.com/egg/nodejs/httpclient-upload 背景 互联网时代,无数服务是基于 HTTP 协议进行通信的. 除了常见的 前端浏览器 - ...

  4. js能否上传文件夹

    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...

  5. 利用ajaxfileupload.js异步上传文件

    1.引入ajaxfileupload.js 2.html代码 <input type="file" id="enclosure" name="e ...

  6. js获取上传文件内容(未完待续)

    js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...

  7. django实现分片上传文件

    目标:利用django实现上传文件功能 1,先设置路由系统 urls.py from django.conf.urls import url,include from django.contrib i ...

  8. Atitit.js获取上传文件全路径

    Atitit.js获取上传文件全路径 1. 默认的value只能获取文件名..安全原因.. 1 2. Firefox浏览器的读取 1 3. Html5 的file api 2 4. 解决方法::使用a ...

  9. js获取上传文件内容

    js 获取上传文件的字节数及内容 <div> 上传文件 : <input type="file" name = "file" id = &qu ...

随机推荐

  1. Cocos Creator 入门

    Cocos Createor 资源 略 场景 节点树 节点与组件 坐标系 脚本 组件声明,生命周期回调 var Component = cc.Class({ // 用于序列化,可省略 name: 's ...

  2. python3好用的mysql.connector库

    python3好用的mysql.connector库 from mysql.connector import connect #建立mysql连接,生成一个mysql.connector对象 conn ...

  3. Spark大数据处理 之 从WordCount看Spark大数据处理的核心机制(1)

    大数据处理肯定是分布式的了,那就面临着几个核心问题:可扩展性,负载均衡,容错处理.Spark是如何处理这些问题的呢?接着上一篇的"动手写WordCount",今天要做的就是透过这个 ...

  4. 简述ref与out区别

    1.相同点:两者都是按地址(引用)传递的,使用后都将改变原来参数的数值. 2.区别:ref可以把参数的数值传递进函数,但是out是要把参数清空(声明时不必显示初始化),就是说你无法把一个数值从out传 ...

  5. SDUT OJ 数据结构实验之链表七:单链表中重复元素的删除

    数据结构实验之链表七:单链表中重复元素的删除 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem ...

  6. Python学习【第五篇】:面向对象及相关

    面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 1 2 3 4 5 6 c ...

  7. 014 Android BottomNavigationView 底部导航组件使用

    1.导入BottomNavigationView组件(点击下载按钮,安装组件) 2.新建菜单 (1)app--->src-->main--->res ,选中res目录右击new--- ...

  8. C++_类继承6-继承和动态内存分配

    如果基类使用动态内存分配,并重新定义赋值和复制构造函数,这将怎样影响派生类的实现?这个问题的答案取决于派生类的属性.如果派生类也使用动态内存分配,那就需要注意学习新的小技巧. 派生类不适用new // ...

  9. POJ_3414 Pots 【复杂BFS】

    一.题面 You are given two pots, having the volume of A and B liters respectively. The following operati ...

  10. 小数据池 is 和 == ,以及再谈编码

    一.小数据池 1.id() 小数据池针对的是:int ,str,boo(都是不可变的数据类型) (1)如果是在py文件中写的字符串,几乎都是缓存的 (2)在黑窗口里写的机会都不会缓存 (3)不同的解释 ...