超大文件上传方案(PHP)

 

2,大文件分片,一片一片的传到服务端,再由服务端合并。这么做的好处在于一旦上传失败只是损失一个分片而已,不用整个文件重传,而且每个分片的大小可以控制在4MB以内,服务端限制在4M即可。

<div class="section section6 section5">

        <tbody id="thelist">

            </tr>

    <div class="selFile" id="selFile">

            <h2 class="txt1">选择视频文件</h2>

    </div>

//引入插件

1// 文件上传

4         $list = $('#thelist'),

7         $part_btn = $('.part1__btn'), //批量上传按钮

10         fileSize = 0,//上传文件的总大小

13     // 所有文件的进度信息,key为file id

16         md5Obj = {},

19         uploader;

22     window.is_confirm = false;

25         if(window.is_confirm !== false)

28

不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级浏览器');

33

36     });

39         //拖拽容器

42         // 不压缩image

45         // swf文件路径

48         // 文件接收服务端。

51         formData: {

54             file_name:''

57         // 选择文件的按钮。可选。

60             id:'#btns__add',

添加视频文件"

64         // 开起分片上传。

67         //如果要分片,分多大一片2M

70         //上传文件的类型

73             extensions: 'mp4,avi,flv',

76         //验证文件总数量, 超出则不允许加入队列。

79         fileSingleSizeLimit:2*1024*1024*1024,

82

85         var data = new Date(),

88             time = data.getFullYear() + "-" + month + "-" + day,

89             $tr = $('<tr class="toBeUploaded" id="'+file.id+'"></tr>'),

90             $td = $('<td class="col1"><input type="checkbox" name="" class="col1__checkBox"/><input type="text" value="'+ file.name +'" name="" class="name"/></td><td class="col2">'+convert_size(file.size)+'</td><td class="col3"><select class="class_id">'+ class_options +'</select></td><td class="col4">读取视频中</td><td class="col5">0%</td><td class="col6"><ul><li class="view"><a target="_blank" href="javascript:;">查看</a></li><li class="delete">删除</li></ul></td>').appendTo($tr),

93             $delbtn = $tr.find('li.delete');

96

99                 case 'exceed_size':

102

上传暂停';

107                 default:

110             }

113             // @todo lazyload

116         }

119             if ( prev === 'progress' ) {

122                 // 开始上传

125             // 成功

128                 showError( file.statusText );

131                 showError( 'interrupt' );

134             } elseif ( cur === 'progress' ) {

137             } elseif ( cur === 'complete' ) {

140             }

143         });

146         });

149     }

152     function removeFile( file ) {

155         delete percentages[ file.id ];

158

161

164         }

167         $upload.addClass( 'state-' + val );

170         switch ( state ) {

173                 break;

176                 uploader.refresh();

179             case 'uploading':

182             case 'paused':

185

188                $upload.text( '开始上传' ).addClass( 'disabled' );

191                 if ( stats.successNum && !stats.uploadFailNum ) {

194                 }

197                 stats = uploader.getStats();

上传成功' );

202                     state = 'done';

205                 break;

208

211     uploader.on( 'fileQueued', function( file ) {

214         $("#upload_num").text(fileCount);

 

219             // 及时显示进度

读取文件'+parseInt(percentage*100)+"%");

224             .then(function(val) {

227             $( '#'+file.id ).find('.col4').text('待上传');

230         addFile( file );

233     // 删除文件

236         fileSize -= file.size;

239         if ( !fileCount ) {

242         removeFile( file );

245

248         id: '#btns__add2',

251

254         var $tr = $('#'+file.id),

257         percentage = parseInt(percentage*100);

260         }

263     };

266     uploader.on( 'uploadStart', function( file ) {

269         var request_data = {

272         };

275             console.log(r);

278                 $( '#'+file.id ).find('.col4').text('视频已存在');

281                 $('.pop2 .video_game').text("所在游戏:"+r.data.game_name);

上传时间:"+r.data.create_time);

285                 $('.popup').show();

288             }else {

291         };

294

297         $tr = $("#"+data.id);

300         var reg = /[1-9][0-9]*/g;

303         data.class_id = class_id;

306

309             $( '#'+file.id ).find('.col4').text('成功上传');

312         }elseif(res.code == 2) {

315             $('#'+file.id).find('.view').find('a').attr('href',playmain +'/?video_id='+ res.data.video_id);

318         }

321     uploader.on( 'uploadError', function( file,reason ) {

324     });

327         $( '#'+file.id ).find('.progress').fadeOut();

330     uploader.on( 'all', function( type ) {

333         } elseif ( type === 'stopUpload' ) {

336             state = 'done';

339         if ( state === 'uploading' ) {

342             $('input.name').attr("disabled","disabled");

345             $('select.class_id').attr("disabled","disabled");

正在上传视频');

350             window.is_confirm = false;

上传完成");

354     });

357     * 验证文件格式以及文件大小

360         var msg = ''

363             case "F_EXCEED_SIZE": msg = "文件大小不能超过1G";break;

一次最多能上传10个文件";break;

367         if(msg != ''){

370     });

373         $('td .col1__checkBox').each(function(){

376                 var id = $tr.attr('id');

379         });

382         var isbreak = false;

 

387         })

390             return;

393             if(!$(this).val()|| $(this).val() == ''){

396         })

399             return;

402             location.reload();

405             returnfalse;

408         $.each(md5Obj,function(index,item){

411             }

414             showError('文件尚未读取完成,请耐心等待');

417         if ( state === 'ready' && md5Ready ) {

420             uploader.upload();

423         }

426

后台(PHP)【仅分片上传相关代码】

  3         $keepFileName = R::string('keepFileName', 0);

  6         $guid = R::string('guid');  //标识视频

  9         $file_name = R::string('file_name');

 12         $this->upload = new Common_Upload();

 15             $this->response_msg(-1, 'guid 或 file_name 或 md5 不能为空');

 18

请上传一个文件');

 23             if($chunks){

 26                     $this->response_msg(-2, '分片上传失败');

 29

 31                 $res = $this->upload->saveFile_nochunks($file, '', '', $keepFileName);

 34             }

 37                 $this->response_msg(-3, '上传文件出错!msg:'.print_r($err, true));

 40             if($unsize_change){

 43                 $size = $this->convert_size($res['size']);

 46             //视频上传完成

 49                 $video_domain = $domain[RUN_MOD]['VIDEO'];

 52                     $res['name'] = $file_name;

 55                     'video_name'=> $file_name,

 58                     'create_time'=> date('y-m-d H:i:s',time()),

 61                     'md5'=>$md5

 64                 $video = $video_mod->save_video($video_data,$guid);

 67                     'chunks'=>$chunks,

 70                     'guid'=> $guid,

 73                     'id'=>$id

视频上传成功',$res);

 78             //非分片上传

 81                 $video_domain = $domain[RUN_MOD]['VIDEO'];

 84                 }

 87                     'video_url'=> $video_domain."/".$res['path'],

 90                     'update_time'=> date('y-m-d H:i:s',time()),

 93                 );

 96                 if(empty($video)){

 99                 }

102                     'video_data'=>$video_data,

105                     'video_id'=>$video[0],

108                 );

111             }

114                 'chunks'=>$chunks,

117             $this->response_msg(2, '分片上传成功',$res);

 

  2     * 保存分片文件(注意先验证文件是否合法)

  5     * @param string $attachdir 上传文件路径

  8     * @return bool

 11     {

 14         }

 17         $file_info = $this->saveFile($file, '', '', false, $file_name,true);

 20             //记录已上传的分片编号,上传顺序并不是按编号顺序进行上传

 23                 $strarr = array();

 26                 }

 29             $file_path = $cache->set($guid.$chunk,$file_info['path'],60 * 60 * 24);

 32             for($i=0;$i<$chunks;$i++){

 35                 }

 38             $file_info['chunks_path_count'] = count($chunk_path_array);

 41                 //按目录类型存储

 44                 $dirType = $this->pre_url.$dirType;

 47                 $saveName ='upload/mp4/'.$month_file_path.'/original/'.$guid.$file_info['type'];

 50                     mkdir($this->attachDIR.'upload/mp4/'.$month_file_path.'/original/',0755,true);

 53                     $fp = fopen($join_file_name, "ab");

 56                         for ($i = 0; $i < $chunks; $i++) {

 59                                 fwrite($fp, fread($handle, filesize($tmp_file)));

 62                                 unlink($tmp_file);//合并完毕的文件就删除

 65                         for($i=0;$i<$chunks;$i++){

 68                         $time = $this->getTime($join_file_name,$file_info['type']);

 71                         $file_info['size'] = filesize($join_file_name);

 74                         $model_mod = new Model_Base();

 77                         //父进程和子进程都会执行下面代码

 80                             die('could not fork');

 83                             //对上传完成的视频进行排队转码

 86                             pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。

 89                             //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。

 92                     }

 95             }

 98                 $this->error[] = '分片上传失败';

101             /*}}}*/

1,实现了分片上传;