分块上传g级文件 (转载)

原理如:3G的大文件分1500个2M二进度文件,通post方法发送给node服务,服务器全部接收到文件后,进组装生成你上文件。

需要了解以下node库,:

async: http://c7.gg/cdFxN
multiparty:http://c7.gg/cdFkN

客户端代码:

 
  1.  
  2. <div class="hei-bg" style="display:block;" >

  3. <div class="user-info" style="display:block;" >

  4. <div class="tc">请上传大文件</div>

  5. <div class="user-pic picw320"><input id="uppic" type="file" ><img id="upimg" src="/img/bbb.jpg"></div>

  6. <div id="jd" class="jdb">进度</div>

  7.  
  8. <div><div id="userbtn" class="bg-main tc userbtn">确定</div></div>

  9. </div>

  10. </div>

  11.  
  12. <script src="./res/js/lib/jquery.min.js"></script>

  13. <script src="./res/js/lib/async.min.js"></script>//异步库

  14.  
  15.  
  16. <script>

  17. $(function(){

  18. $('#userbtn').on('click',function(){

  19. var file= $("#uppic")[0].files[0],//上传文件主体

  20. name = file.name, //文件名

  21. size = file.size, //总大小

  22. succeed = 0; //当前上传数

  23. var shardSize = 2 *1024*1024, //以2MB为一个分片

  24. shardCount = Math.ceil(size / shardSize); //总片数

  25.  
  26. /*生成上传分片文件顺充,通过async.eachLimit()进行同步上传

  27. attr里面是[0,1,2,3...,最后一位]

  28. */

  29. var attr=[];

  30. for(var i=0;i<shardCount;++i){

  31. attr.push(i);

  32. }

  33.  
  34.  
  35.  
  36. async.eachLimit(attr,1,function(item,callback){

  37. var i=item;

  38. var start = i * shardSize,//当前分片开始下标

  39. end = Math.min(size, start + shardSize);//结束下标

  40.  
  41. //构造一个表单,FormData是HTML5新增的

  42. var form = new FormData();

  43. form.append("data", file.slice(start,end)); //slice方法用于切出文件的一部分

  44. form.append("name", name);//文件名字

  45. form.append("total", shardCount); //总片数

  46. form.append("index", i + 1); //当前片数

  47. //Ajax提交

  48.  
  49. $.ajax({

  50. url: "/dafile",

  51. type: "POST",

  52. data: form,

  53. timeout:120*1000,

  54. async: false, //同步

  55. processData: false, //很重要,告诉jquery不要对form进行处理

  56. contentType: false, //很重要,指定为false才能形成正确的Content-Type

  57. success: function(data){

  58. ++succeed;

  59. var data=eval('('+data+')');

  60. /*返回code为0是成功上传,1是请继续上传*/

  61. if(data.code==0){

  62. console.log(data.msg);

  63. }else if(data.code==1){

  64. console.log(data.msg);

  65. }

  66. //生成当前进度百分比

  67. var jd=Math.round(succeed/shardCount*100)+'%';

  68. $('.jdb').html(jd);

  69. /*如果是线上,去掉定时,直接callback(),

  70. 这样写是为方便,本地测试看到进度条变化

  71. 因为本地做上传测试是秒传,没有时间等待*/

  72. setTimeout(callback,50);

  73. }

  74. });

  75. },function(err){

  76. console.log('上传成功');

  77. });

  78. });

  79. });

  80. </script>

服务器代码:

 
  1. function user(req,res,config){

  2. var path=require('path');

  3. var fs=require('fs');

  4. var multiparty = require('multiparty');//文件上传模块

  5. var async = require('async');//异步模块

  6. var form = new multiparty.Form();//新建表单

  7.  
  8. //设置编辑

  9. form.encoding = 'utf-8';

  10. //设置文件存储路径

  11. form.uploadDir = "Uploads/img/";

  12. //设置单文件大小限制

  13. // form.maxFilesSize = 200 * 1024 * 1024;

  14. /*form.parse表单解析函数,fields是生成数组用获传过参数,files是bolb文件名称和路径*/

  15. form.parse(req, function (err,fields,files) {

  16. files=files['data'][0];//获取bolb文件

  17. var index=fields['index'][0];//当前片数

  18. var total=fields['total'][0];//总片数

  19. var name=fields['name'][0];//文件名称

  20. var url='Uploads/img/'+name+index;//临时bolb文件新名字

  21. fs.renameSync(files.path,url);//修改临时文件名字

  22.  
  23. var pathname='Uploads/img/'+name;//上传文件存放位置和名称

  24. if(index==total){//当最后一个分片上传成功,进行合并

  25. /*

  26. 检查文件是存在,如果存在,重新设置名称

  27. */

  28. fs.access(pathname,fs.F_OK,(err) => {

  29. if(!err){

  30. var myDate=Date.now();

  31. pathname='Uploads/img/'+myDate+name;

  32. console.log(pathname);

  33.  
  34. }

  35. });

  36. //这里定时,是做异步串行,等上执行完后,再执行下面

  37. setTimeout(function(){

  38. /*进行合并文件,先创建可写流,再把所有BOLB文件读出来,

  39. 流入可写流,生成文件

  40. fs.createWriteStream创建可写流

  41. aname是存放所有生成bolb文件路径数组:

  42. ['Uploads/img/3G.rar1','Uploads/img/3G.rar2',...]

  43. */

  44. var writeStream=fs.createWriteStream(pathname);

  45. var aname=[];

  46. for(var i=1;i<=total;i++){

  47. var url='Uploads/img/'+name+i;

  48. aname.push(url);

  49. }

  50.  
  51. //async.eachLimit进行同步处理

  52. async.eachLimit(aname,1,function(item,callback){

  53. //item 当前路径, callback为回调函数

  54. fs.readFile(item,function(err,data){

  55. if(err)throw err;

  56. //把数据写入流里

  57. writeStream.write(data);

  58. //删除生成临时bolb文件

  59. fs.unlink(item,function(){console.log('删除成功');})

  60. callback();

  61. });

  62. },function(err){

  63. if (err) throw err;

  64. //后面文件写完,关闭可写流文件,文件已经成生完成

  65. writeStream.end();

  66. //返回给客服端,上传成功

  67. var data=JSON.stringify({'code':0,'msg':'上传成功'});

  68. res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});

  69. res.end(data);//返回数据

  70. });

  71. },50);

  72.  
  73. }else{//还没有上传文件,请继续上传

  74. var data=JSON.stringify({'code':1,'msg':'继续上传'});

  75. res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});

  76. res.end(data);//返回数据

  77. }

  78. });

  79. return user;

  80. };

  81. exports.init = user;

  82.  
  83.  
  84. 这是初步设计方案,后期加异步上传和断点续传功能。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值