100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 无插件实现大文件分片上传 断点续传

无插件实现大文件分片上传 断点续传

时间:2020-06-04 15:12:22

相关推荐

无插件实现大文件分片上传 断点续传

代码地址如下:

/demo/11888.html

1. 简介:

本篇文章基于实际项目的开发,将介绍项目中关于大文件分片上传、文件验证、断点续传、手动重试上传等需求的使用场景及实现;

2. 项目需求

#####1. 在一个音视频的添加中,既要有音视频的简介(如音视频内容文字介绍、自定义主题名称等一些基本的信息),又要有音视频所需要的多个文件(就像电视剧,一部电视剧有多集一样)。在数据库中具体表现为一对多的关系,即一个视频对应多个文件。下文就以电视剧为例

#####2. 如果一个电视剧中,既有上百兆的,也有几十兆的视频,但是如果在不稳定的一个网络环境中,c传输大文件时,客户想先把小的视频上传了,之后再来继续传未传完的大文件声誉部分,这就需要断点续传的功能;

#####3. 电视剧中至少有一集(至少有一个文件),无文件的电视剧基本信息无效;

3. 需求分析

1. 确定电视剧基本信息(自定义名称,内容简介、演员简介、播出时间等)及文件的上传方式

- 基本信息和音视频文件分开上传(因为在原有的数据库表设计中,文件表是关联于基本信息,所以必须要有音视频主键,才能在数据库添加对应的文件信息),取得基本信息主键之后再去上传文件;

2. 文件断点续传中,如何分片;文件接收方式;服务器端如何判断是哪个文件的分片;如何拼接各个分片;上传过程中发生意外情况(如断网,关闭浏览器),如何处理?

- 分片方式: 在客户端进行分片;- 服务器端接收方式:使用MultipartFile接收文件- 服务器端确定是哪个文件的分片: 在客户端按照一定规则(UUID或其他方式)生成唯一名称,在服务器端直接找到与该名称相同的文件片段;- 拼接文件分片: 使用NIO的方式,将分片追加到已有分片的后面;- 上传中发生意外: A. 断网: 该情况类似于暂停上传,上传到文件处于暂停状态,网络恢复,即可点击继续上传按钮,继续上传;B. 关闭浏览器: 在关闭时,给用户提示框,询问是否继续保存,若不保存,则根据视频基本信息表的主键的删除脏数据;C. 第一个文件在上传时候,被用户取消或者断网,则服务器端未修改基本信息为有效,并且也未标记该文件为有效记录,可以理解为脏数据,但不需要清理这些数据(在查询的时候,不能查出这些无效记录,可以在更新视频基本信息记录的时候,查找这些脏数据,并清理磁盘上及数据表中的记录);

4. 实现

1. 基于以上分析,搭建一个简单的web项目工程,如下图:
2. 前端主要功能实现

// 文件分割上传// 文件大小和分割起点// 注释的是本地存储实现var size = file.size, start = localStorage[fileid] * 1 || 0;//start = $("filelist_" + fileid).filesize;console.log("start1:"+start);if (size == start) {// 已经传过了fileArray.shift();if (delete fileArray[fileid]) console.log(fileArray.join() + "---上传成功");objStateElement.success(fileid, now);// 回调onsuccess.call(fileid, {});localStorage.clear();return;}var funFileSize = function() {if (file.flagPause == true) {onpause.call(fileid);return;}var data = new FormData();data.append("name", encodeURIComponent(file.name));data.append("fileid", fileid);data.append("file", file.slice(start, start + fileSplitSize));data.append("start", start + "");var p = "?name="+encodeURIComponent(file.name)+"&fileid"+fileid+"&start"+start;// XMLHttpRequest 2.0 请求var xhr = new XMLHttpRequest();xhr.open("post", eleForm.action, true); // 上传进度中xhr.upload.addEventListener("progress", function(e) {objStateElement.backgroundSize(fileid, (e.loaded + start) / size * 100);}, false);// ajax成功后xhr.onreadystatechange = function(e) {if (xhr.readyState == 4) {if (xhr.status == 200) {try {var json = JSON.parse(xhr.responseText);} catch (e) {objStateElement.error(fileid);return;} //var json = JSON.parse(xhr.responseText);if (!json || !json.succ) {objStateElement.error(fileid);onerror.call(fileid, json);return;}if (start + fileSplitSize >= size) {// 超出,说明全部分割上传完毕// 上传队列中清除者一项fileArray.shift();if (delete fileArray[fileid]) console.log(fileArray.join() + "---上传成功");objStateElement.success(fileid, now);// 回调onsuccess.call(fileid, json);localStorage.clear();} else {// 尚未完全上传完毕 // 改变下一部分文件的起点位置start += fileSplitSize;// 存储上传成功的文件点,以便出现意外的时候,下次可以断点续传localStorage.setItem(fileid, start + ""); // 上传下一个分割文件funFileSize();} } else {objStateElement.error(fileid);}}};

前端向后台提交文件

var xhr_filesize = new XMLHttpRequest();xhr_filesize.open("GET", "/BigFileUpload/ajaxFilesUploadServlet?filename=" + nameArray.join(), true);xhr_filesize.onreadystatechange = function(e) {if (xhr_filesize.readyState == 4) {if (xhr_filesize.status == 200 && xhr_filesize.responseText) {var json = JSON.parse(xhr_filesize.responseText);if (json.succ && json.data) {for (var key in json.data) {if (json.data[key] > 0 && json.data[key] < fileArray[key].size) {objStateElement.backgroundSize(key, json.data[key] / fileArray[key].size * 100);objStateElement.keep(key);} $("filelist_" + key).filesize = json.data[key];}}}}};xhr_filesize.send();}

3.后台接收文件

/**** @Description: 上传流文件并保存* @param request* @param response* @throws ServletException* @throws IOException* @version: v1.1.0* @author: xiangdong.she* @date: Nov 9, ** Modification History:* Date AuthorVersion Description*-------------------------------------------------------------* Nov 9, xiangdong.shev1.1.0修改原因*/public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{request.setCharacterEncoding("utf-8"); //设置编码JSONObject json = new JSONObject(); //返回的json串String filename = ""; //文件名称String path = request.getRealPath("/upload"); //获取文件需要上传到的路径try{List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);for (FileItem item : items){if (item.isFormField()){String fieldname = item.getFieldName();String fieldvalue = "";if (fieldname.equals("name")){filename = fieldvalue = URLDecoder.decode(item.getString(),"UTF-8");}else{fieldvalue = item.getString();}System.out.println("fieldname:" + fieldname+ "--fieldvalue:" + fieldvalue);// to do list}else{String fieldname = item.getFieldName();InputStream filecontent = item.getInputStream();System.out.println("fieldname:" + fieldname + "--filename:"+ filename + "---filecontent:" + filecontent+ "---path:" + path);//手动写入硬盘if (makeDir(path)){createFile(path, filename);}File file = new File(path + File.separator + filename);FileOutputStream fos = new FileOutputStream(file, true);InputStream is = item.getInputStream();IOUtils.copy(is, fos);is.close();fos.close();System.out.println("获取上传文件的总共的容量:" + item.getSize());}}}catch (FileUploadException e){e.printStackTrace();}catch (Exception e){e.printStackTrace();}json.put("succ", true);response.setContentType("text/plain");response.getWriter().write(json.toString());}

5.结果展现

无插件实现大文件分片上传,断点续传

代码地址如下:

/demo/11888.html

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。