spring boot 는 어떻게 절단 블록 업 로드 를 실현 합 니까?

이 글 은 주로 spring boot 가 절단 분 편 업 로드 를 어떻게 실현 하 는 지 를 소개 합 니 다.글 에서 예시 코드 를 통 해 매우 상세 하 게 소개 되 었 고 여러분 의 학습 이나 업무 에 대해 어느 정도 참고 학습 가 치 를 가지 기 때문에 필요 한 친 구 는 참고 하 셔 도 됩 니 다.
파일 업 로드 는 웹 개발 에서 자주 볼 수 있 는 것 입 니 다.
springboot 의 기본 설정 은 10MB 이 고 10M 이상 은 서버 에 전송 되 지 않 습 니 다.기본 설정 을 수정 해 야 합 니 다.
하지만 지원 하 는 큰 파일 을 수정 하면 서버 의 부담 이 커진다.
파일 이 어느 정도 크 면 서버 가 대량의 메모 리 를 차지 할 뿐만 아니 라 http 전송 이 중 단 될 수 있 습 니 다.
절단 편 으로 업로드 할 수 있 습 니 다.
html 5 에서 제공 하 는 파일 API 에서 파일 을 쉽게 분할 하여 자 른 다음 ajax 비동기 처 리 를 통 해 서버 에 데 이 터 를 전송 하여 큰 파일 업로드 에 대한 제한 을 돌파 할 수 있 습 니 다.
이 동시에 비동기 처 리 는 어느 정도 파일 업로드 의 효율 을 높 였 다.
프로 세 스 설명:
  • 파일 을 N 조각 으로 나 눕 니 다
  • 4.567917.분 편 을 처리 하고 프론트 데스크 는 업로드 인 터 페 이 스 를 여러 번 호출 하 며 매번 파일 의 일부분 을 서버 에 업로드 합 니 다
  • N 개의 필름 을 모두 업로드 한 후 N 개의 파일 을 하나의 파일 로 통합 하고 N 개의 필름 파일 을 삭제 합 니 다
  • 1.서버
    (1)의존 도 추가
    
    <dependency>
       <groupId>commons-fileupload</groupId>
       <artifactId>commons-fileupload</artifactId>
       <version>1.3.3</version>
    </dependency>
    (2)UploadController
    
    package com.example.demo.controller;
    
    import com.example.demo.core.Result;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.commons.io.FileUtils;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    @CrossOrigin
    @Controller
    @RequestMapping("/api/upload")
    public class UploadController {
      @PostMapping("/part")
      @ResponseBody
      public Result bigFile(HttpServletRequest request, HttpServletResponse response, String guid, Integer chunk, MultipartFile file, Integer chunks) {
        try {
          String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
          ;
          boolean isMultipart = ServletFileUpload.isMultipartContent(request);
          if (isMultipart) {
            if (chunk == null) chunk = 0;
            //               
            String tempFileDir = projectUrl + "/upload/" + guid;
            File parentFileDir = new File(tempFileDir);
            if (!parentFileDir.exists()) {
              parentFileDir.mkdirs();
            }
            //      ,           ,               
            File tempPartFile = new File(parentFileDir, guid + "_" + chunk + ".part");
            FileUtils.copyInputStreamToFile(file.getInputStream(), tempPartFile);
          }
    
        } catch (Exception e) {
          return Result.failMessage(400,e.getMessage());
        }
        return Result.successMessage(200,"    ");
      }
    
      @RequestMapping("merge")
      @ResponseBody
      public Result mergeFile(String guid, String fileName) {
        //    destTempFile        
        String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
        try {
          String sname = fileName.substring(fileName.lastIndexOf("."));
          //       
          Date currentTime = new Date();
          SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
          //            
          String timeStamp = simpleDateFormat.format(currentTime);
          //       
          String newName = timeStamp + sname;
          simpleDateFormat = new SimpleDateFormat("yyyyMM");
          String path = projectUrl + "/upload/";
          String tmp = simpleDateFormat.format(currentTime);
          File parentFileDir = new File(path + guid);
          if (parentFileDir.isDirectory()) {
            File destTempFile = new File(path + tmp, newName);
            if (!destTempFile.exists()) {
              //          ,       ,     
              destTempFile.getParentFile().mkdir();
              try {
                destTempFile.createNewFile();
              } catch (IOException e) {
                e.printStackTrace();
              }
            }
            for (int i = 0; i < parentFileDir.listFiles().length; i++) {
              File partFile = new File(parentFileDir, guid + "_" + i + ".part");
              FileOutputStream destTempfos = new FileOutputStream(destTempFile, true);
              //  "      " "    " 
              FileUtils.copyFile(partFile, destTempfos);
              destTempfos.close();
            }
            //             
            FileUtils.deleteDirectory(parentFileDir);
            return Result.successMessage(200,"    ");
          }else{
            return Result.failMessage(400,"     ");
          }
    
        } catch (Exception e) {
          return Result.failMessage(400,e.getMessage());
        }
    
      }
    
    }
    설명:
    주해@CrossOrigin 크로스 도 메 인 문제 해결
    (3)Result
    
    package com.example.demo.core;
    
    import com.alibaba.fastjson.JSON;
    
    /**
     * Created by Beibei on 19/02/22
     * API    
     */
    public class Result<T> {
      private int code;
      private String message;
      private T data;
    
      public Result setCode(Integer code) {
        this.code = code;
        return this;
      }
    
      public int getCode() {
        return code;
      }
    
      public String getMessage() {
        return message;
      }
    
      public Result setMessage(String message) {
        this.message = message;
        return this;
      }
    
      public T getData() {
        return data;
      }
    
      public Result setData(T data) {
        this.data = data;
        return this;
      }
    
      @Override
      public String toString() {
        return JSON.toJSONString(this);
      }
    
      public static <T> Result<T> fail(Integer code,T data) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setData(data);
        return ret;
      }
    
      public static <T> Result<T> failMessage(Integer code,String msg) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setMessage(msg);
        return ret;
      }
      public static <T> Result<T> successMessage(Integer code,String msg) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setMessage(msg);
        return ret;
      }
    
      public static <T> Result<T> success(Integer code,T data) {
        Result<T> ret = new Result<T>();
        ret.setCode(code);
        ret.setData(data);
        return ret;
      }
    
    }
    2.전단
    (1)플러그 인 사용
    웹 업로드,다운로드   https://github.com/fex-team/webuploader/releases
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <link href="css/webuploader.css" rel="external nofollow" rel="stylesheet" type="text/css" />
      <script type="text/javascript" src="jquery-1.10.1.min.js"></script>
      <script type="text/javascript" src="dist/webuploader.min.js"></script>
    </head>
    <body>
      <div id="uploader">
       <div class="btns">
         <div id="picker">    </div>
         <button id="startBtn" class="btn btn-default">    </button>
       </div>
      </div>
    </body>
    <script type="text/javascript">
    var GUID = WebUploader.Base.guid();//  GUID
    var uploader = WebUploader.create({
      // swf    
      swf: 'dist/Uploader.swf',
      //        。
      server: 'http://localhost:8080/api/upload/part',
      formData:{
        guid : GUID
      },
      pick: '#picker',
      chunked : true, //     
      chunkSize : 1 * 1024 * 1024, //   1M,
      chunkRetry : false,//     ,    
      threads : 1,//      。           。
      resize: false
    });
    $("#startBtn").click(function () {
      uploader.upload();
    });
    //          。
    uploader.on( "uploadSuccess", function( file ) {
      $.post('http://localhost:8080/api/upload/merge', { guid: GUID, fileName: file.name}, function (data) {
        if(data.code == 200){
         alert('    !');
        }
       });
    });
    </script>
    </html>

    (2)플러그 인 사용 안 함
    직접 HTML 5 의 File API 로
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <script src="jquery-1.10.1.min.js" type="text/javascript">
        </script>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
      </head>
      <body>
        <div id="uploader">
          <div class="btns">
            <input id="file" name="file" type="file"/>
            <br>
              <br>
                <button id="startBtn">
                      
                </button>
              </br>
            </br>
          </div>
          <div id="output">
          </div>
        </div>
      </body>
      <script type="text/javascript">
        var status = 0;
        var page = {
        init: function(){
          $("#startBtn").click($.proxy(this.upload, this));
        },
        upload: function(){
          status = 0;
          var GUID = this.guid();
          var file = $("#file")[0].files[0], //    
            name = file.name,    //   
            size = file.size;    //   
          var shardSize = 20 * 1024 * 1024,  // 1MB     
            shardCount = Math.ceil(size / shardSize); //   
          for(var i = 0;i < shardCount;++i){
            //             
            var start = i * shardSize,
            end = Math.min(size, start + shardSize);
            var partFile = file.slice(start,end);
            this.partUpload(GUID,partFile,name,shardCount,i);
          }
        },
        partUpload:function(GUID,partFile,name,chunks,chunk){
          //      ,FormData HTML5   
          var now = this;
          var form = new FormData();
          form.append("guid", GUID);
          form.append("file", partFile); //slice            
          form.append("fileName", name);
          form.append("chunks", chunks); //   
          form.append("chunk", chunk);    //      
            //Ajax  
            $.ajax({
              url: "http://localhost:8080/api/upload/part",
              type: "POST",
              data: form,
              async: true,    //  
              processData: false, //   ,  jquery   form    
              contentType: false, //   ,   false       Content-Type
              success: function(data){
                status++;
                if(data.code == 200){
                  $("#output").html(status+ " / " + chunks);
                }
                if(status==chunks){
                  now.mergeFile(GUID,name);
                }
              }
            });
        },
        mergeFile:function(GUID,name){
          var formMerge = new FormData();
          formMerge.append("guid", GUID);
          formMerge.append("fileName", name);
          $.ajax({
            url: "http://localhost:8080/api/upload/merge",
            type: "POST",
            data: formMerge,
            processData: false, //   ,  jquery   form    
            contentType: false, //   ,   false       Content-Type
            success: function(data){
              if(data.code == 200){
                alert('    !');
              }
            }
          });
        },
        guid:function(prefix){
            var counter = 0;
            var guid = (+new Date()).toString( 32 ),
              i = 0;
            for ( ; i < 5; i++ ) {
              guid += Math.floor( Math.random() * 65535 ).toString( 32 );
            }
            return (prefix || 'wu_') + guid + (counter++).toString( 32 );
        }
      };
    
      $(function(){
        page.init();
      });
      </script>
    </html>

    3.최적화
    springboot 의 기본 설정 은 10MB 이 며,전단 을 20M 으로 변경 하면 오류 가 발생 합 니 다.
    
    org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (10486839) exceeds the configured maximum (10485760)
    해결 방법:
    src/main/resources 의 application.properties 에 추가
    
    spring.servlet.multipart.max-file-size=30MB
    spring.servlet.multipart.max-request-size=35MB
    설명:
    설정 한 수 치 는 전단 에서 전해 오 는 것 과 같 지만,잘못 보고 하기 쉽 지 않다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기