zoukankan      html  css  js  c++  java
  • 大文件分片上传demo

    主要思路就是将大文件分成多个小文件上传,服务器端将上传上来的小文件先保存成各个临时文件,当所有分片的文件上传完毕后,调用接口将所有的临时文件合并成一个文件

    我这里只是一个小小的demo,如果想做好,首先是前端根据文件获取到一个md5值,然后在上传文件的时候根据这个md5值检测之前是否有上传文件,如果没有则从开始位置上传(上传成功后要把相应的数据保存到数据库表里面),如果之前有上传则查看上传到了什么位置,然会给前端,前端好接着从之前的位置传数据

    后台代码

    package cn.com.modules.file;
    
    import lombok.Data;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.Serializable;
    
    /**
     * @Author: luojie
     * @Date: 2021/2/20 11:09
     */
    @Data
    public class Chunk implements Serializable {
    
        private Long id;
        /**
         * 当前文件块,从1开始
         */
        private Integer chunkNumber;
        /**
         * 分块大小
         */
        private Long chunkSize;
        /**
         * 当前分块大小
         */
        private Long currentChunkSize;
        /**
         * 总大小
         */
        private Long totalSize;
        /**
         * 文件标识
         */
        private String identifier;
        /**
         * 文件名
         */
        private String filename;
        /**
         * 相对路径
         */
        private String relativePath;
        /**
         * 总块数
         */
        private Integer totalChunks;
        /**
         * 文件类型
         */
        private String type;
    
        private MultipartFile file;
    }
    

      

    package cn.com.esrichina.sip.modules.file;
    
    import cn.com.esrichina.sip.commons.exception.RaccoonException;
    import io.swagger.annotations.Api;
    import org.apache.commons.io.FileUtils;
    import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * @Author: luojie
     * @Date: 2021/2/20 11:10
     */
    @RestController
    @Api(value = "/upload", description = "文件上传,支持文件分片上传")
    @RequestMapping("/upload")
    @CrossOrigin
    public class UploadController {
    
    
        private static final String filePath = "C:/resources/sip";
    
    
        private static final String filePathTemp = "C:/resources/sip/temp";
    
        /**
         * 分片上传
         */
        @RequestMapping(method = RequestMethod.POST)
        @ResponseBody
        public Boolean upload(HttpServletRequest request, Chunk chunk) throws IOException {
    
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            if (isMultipart) {
                MultipartFile file = chunk.getFile();
    
                if (file == null) {
                    throw new RaccoonException(400, "参数验证失败!");
                }
    
                Integer chunkNumber = chunk.getChunkNumber();
                if (chunkNumber == null) {
                    chunkNumber = 0;
                }
    
                java.io.File outFile = new java.io.File(filePathTemp + java.io.File.separator + chunk.getIdentifier(), chunkNumber + ".part");
    
                InputStream inputStream = file.getInputStream();
                FileUtils.copyInputStreamToFile(inputStream, outFile);
            }
    
            return true;
        }
    
        /**
         * 合并所有分片
         * guid 就是 identifier(文件标识)
         */
        @GetMapping("/merge")
        @ResponseBody
        public Boolean mergeFile(String filename, String guid) throws Exception {
    
            java.io.File file = new java.io.File(filePathTemp + java.io.File.separator + guid);
            if (file.isDirectory()) {
                java.io.File[] files = file.listFiles();
                if (files != null && files.length > 0) {
                    java.io.File partFile = new java.io.File(filePath + java.io.File.separator + filename);
                    for (int i = 1; i <= files.length; i++) {
                        java.io.File s = new java.io.File(filePathTemp + java.io.File.separator + guid, i + ".part");
                        FileOutputStream destTempfos = new FileOutputStream(partFile, true);
                        FileUtils.copyFile(s, destTempfos);
                        destTempfos.close();
                    }
                    FileUtils.deleteDirectory(file);
                }
            }
            return true;
        }
    }
    

      

      前端测试代码

    <!doctype html>
    <html lang="en">
     <head>
      <meta charset="UTF-8">
      <meta name="Generator" content="EditPlus®">
      <meta name="Author" content="">
      <meta name="Keywords" content="">
      <meta name="Description" content="">
      <title>Document</title>
     </head>
     <body>
      <form id="f" method="post" action="#"  enctype="multipart/form-data">
    	选择图片:<input type="file" id="file6" name="file1"><br />
    	
    </form>
    <a href="#" class="btnFile6">提交</a>
    <script src="jquery-3.0.0.js"></script>
    <script>
    $(function(){
    $(".btnFile6").click(function () { 
         var upload = function (file, skip) {
             var formData = new FormData();//初始化一个FormData对象
             var blockSize = 1024*1024;//每块的大小
             var nextSize = Math.min((skip + 1) * blockSize, file.size);//读取到结束位置             
             var fileData = file.slice(skip * blockSize, nextSize);//截取 部分文件 块
             formData.append("file", fileData);//将 部分文件 塞入FormData
             formData.append("fileName", file.name);//保存文件名字
    		 formData.append("chunkSize", blockSize);
    		 formData.append("totalSize", file.size);
    		 formData.append("identifier", "AA");
    			formData.append("chunkNumber", (skip + 1));
             $.ajax({
                 url: "http://127.0.0.1:10089/upload",
                 type: "POST",
                 data: formData,
                 processData: false,  // 告诉jQuery不要去处理发送的数据
                 contentType: false,   // 告诉jQuery不要去设置Content-Type请求头
                 success: function (responseText) {
                     $(".result").html("已经上传了" + (skip + 1) + "块文件");
                     if (file.size <= nextSize) {//如果上传完成,则跳出继续上传
                         //全部上传成功后执行下面的语句
    					 console.log("--上传完成----");
    					 //合并文档
    					 $.ajax({
    						type: "GET",
    						url: "http://127.0.0.1:10089/upload/merge?filename=开发文档.docx&guid=AA",
    						dataType: "json",
    						success:function (message) {
    						},
    						error:function (message) {
    							alert('系统异常');
    						}
    					});
                         return;
                     }
                     upload(file, ++skip);//递归调用
    				 
                 }
             });
         };
     
         var file = $("#file6")[0].files[0];
         upload(file, 0);
     });
    })
    	
    </script>
     </body>
    </html>
    

      

  • 相关阅读:
    asp.net 中input radio checked 无效
    AD对象DirectoryEntry本地开发
    Linux部署
    spring 定时任务配置使用
    闲言碎语
    javascript 折后保留一位小数
    JSON 实力应用
    水晶报表(crystal report )中显示CheckBox
    html 笔记
    转载-js按回车键实现登陆-myself
  • 原文地址:https://www.cnblogs.com/james-roger/p/14421317.html
Copyright © 2011-2022 走看看