原理如:3G的大文件分1500个2M二进度文件,通post方法发送给node服务,服务器全部接收到文件后,进组装生成你上文件。
需要了解以下node库,:
async: http://caolan.github.io/async/
multiparty:https://www.npmjs.com/package/multiparty
客户端代码:
<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" ><img id="upimg" src="/img/bbb.jpg"></div>
<div id="jd" class="jdb">进度</div>
<div><div id="userbtn" class="bg-main tc userbtn">确定</div></div>
</div>
</div>
<script src="./res/js/lib/jquery.min.js"></script>
<script src="./res/js/lib/async.min.js"></script>//异步库
<script>
$(function(){
$('#userbtn').on('click',function(){
var file= $("#uppic")[0].files[0],//上传文件主体
name = file.name, //文件名
size = file.size, //总大小
succeed = 0; //当前上传数
var shardSize = 2 *1024*1024, //以2MB为一个分片
shardCount = Math.ceil(size / shardSize); //总片数
/*生成上传分片文件顺充,通过async.eachLimit()进行同步上传
attr里面是[0,1,2,3...,最后一位]
*/
var attr=[];
for(var i=0;i<shardCount;++i){
attr.push(i);
}
async.eachLimit(attr,1,function(item,callback){
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: "/dafile",
type: "POST",
data: form,
timeout:120*1000,
async: false, //同步
processData: false, //很重要,告诉jquery不要对form进行处理
contentType: false, //很重要,指定为false才能形成正确的Content-Type
success: function(data){
++succeed;
var data=eval('('+data+')');
/*返回code为0是成功上传,1是请继续上传*/
if(data.code==0){
console.log(data.msg);
}else if(data.code==1){
console.log(data.msg);
}
//生成当前进度百分比
var jd=Math.round(succeed/shardCount*100)+'%';
$('.jdb').html(jd);
/*如果是线上,去掉定时,直接callback(),
这样写是为方便,本地测试看到进度条变化
因为本地做上传测试是秒传,没有时间等待*/
setTimeout(callback,50);
}
});
},function(err){
console.log('上传成功');
});
});
});
</script>
服务器代码:
function user(req,res,config){
var path=require('path');
var fs=require('fs');
var multiparty = require('multiparty');//文件上传模块
var async = require('async');//异步模块
var form = new multiparty.Form();//新建表单
//设置编辑
form.encoding = 'utf-8';
//设置文件存储路径
form.uploadDir = "Uploads/img/";
//设置单文件大小限制
// form.maxFilesSize = 200 * 1024 * 1024;
/*form.parse表单解析函数,fields是生成数组用获传过参数,files是bolb文件名称和路径*/
form.parse(req, function (err,fields,files) {
files=files['data'][0];//获取bolb文件
var index=fields['index'][0];//当前片数
var total=fields['total'][0];//总片数
var name=fields['name'][0];//文件名称
var url='Uploads/img/'+name+index;//临时bolb文件新名字
fs.renameSync(files.path,url);//修改临时文件名字
var pathname='Uploads/img/'+name;//上传文件存放位置和名称
if(index==total){//当最后一个分片上传成功,进行合并
/*
检查文件是存在,如果存在,重新设置名称
*/
fs.access(pathname,fs.F_OK,(err) => {
if(!err){
var myDate=Date.now();
pathname='Uploads/img/'+myDate+name;
console.log(pathname);
}
});
//这里定时,是做异步串行,等上执行完后,再执行下面
setTimeout(function(){
/*进行合并文件,先创建可写流,再把所有BOLB文件读出来,
流入可写流,生成文件
fs.createWriteStream创建可写流
aname是存放所有生成bolb文件路径数组:
['Uploads/img/3G.rar1','Uploads/img/3G.rar2',...]
*/
var writeStream=fs.createWriteStream(pathname);
var aname=[];
for(var i=1;i<=total;i++){
var url='Uploads/img/'+name+i;
aname.push(url);
}
//async.eachLimit进行同步处理
async.eachLimit(aname,1,function(item,callback){
//item 当前路径, callback为回调函数
fs.readFile(item,function(err,data){
if(err)throw err;
//把数据写入流里
writeStream.write(data);
//删除生成临时bolb文件
fs.unlink(item,function(){console.log('删除成功');})
callback();
});
},function(err){
if (err) throw err;
//后面文件写完,关闭可写流文件,文件已经成生完成
writeStream.end();
//返回给客服端,上传成功
var data=JSON.stringify({'code':0,'msg':'上传成功'});
res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
res.end(data);//返回数据
});
},50);
}else{//还没有上传文件,请继续上传
var data=JSON.stringify({'code':1,'msg':'继续上传'});
res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
res.end(data);//返回数据
}
});
return user;
};
exports.init = user;
//这是初步设计方案,后期加异步上传和断点续传功能。。
用node搞web服务和直接用tomcat、Apache做服务器不太一样, 很多工作都需要自己做。缓存策略也要自己选择,虽然有像koa-static,express.static这些东西可以用来管理静态资源,但是为了开发或配置时更加得心应手,知其所以然,有了解http缓存的必要。另外,http缓存作为一个前端优化的一个要点,也应该有所了解。
Node.js是服务器端的 JavaScript 运行环境,它具有无阻塞(non-blocking)和事件驱动(event-driven)等的特色。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
CORS 是“跨域资源共享”的简写。它是一种允许或限制向 Web 服务器上请求资源的机制,具体取决于进行 HTTP 请求的位置。
我非常喜欢使用 Node.js,但是当涉及到计算密集型的场景时 Node.js 就不能够很好地胜任了。而在这样的情况下 C++ 是一个很好的选择,非常幸运 Node.js 官方提供了C/C++ Addons 的机制让我们能够使用 V8 API 把 Node.js 和 C++ 结合起来。
Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。Node.js 几乎每一个 API 都是支持回调函数的
Stream(流) 是 Node.js 中处理流式数据的抽象接口。 stream 模块用于构建实现了流接口的对象。Node.js 提供了多种流对象。 例如,对 HTTP 服务器的request请求和 process.stdout(标准输出), 都是流的实例
Node 对 ES6 Module 的支持又有新进展。一个新的 PR 更新了当前 --experimental-modules 的实现方案。type 动态判断模块加载模式:更新后的方案将根据 package.json 文件中指定的 type 值来判断 js 文件是使用 ESM 还是 commonjs
Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境,一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。
接触前端也有一段时间了,逐渐开始接触Node.js,刚刚接触Node.js的时候一直都以为Node.js就是JavaScript,当对Node.js有一定的了解之后,其实并不然两者之间有关系,其中的关系又不是必然的,对Node.js进行的一些了解
日常开发需求中有时候为了追求灵活性或降低开发难度,会在业务代码里直接使用 eval/Function/vm 等功能,其中 eval/Function 算是动态执行 JS,但无法屏蔽当前执行环境的上下文,但 node.js 里提供了 vm 模块,相当于一个虚拟机
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!