복붙노트

[SPRING] Spring - 로컬 파일 시스템에 저장하지 않고 대량의 멀티 파트 파일 업로드를 데이터베이스로 스트리밍하는 방법

SPRING

Spring - 로컬 파일 시스템에 저장하지 않고 대량의 멀티 파트 파일 업로드를 데이터베이스로 스트리밍하는 방법

스프링 부트의 기본 MultiPartResolver 인터페이스는 멀티 파트 파일을 로컬 파일 시스템에 저장하여 업로드를 처리합니다. 컨트롤러 메소드가 시작되기 전에 전체 멀티 파트 파일이 서버로 업로드를 완료해야합니다.

업로드 된 모든 파일을 데이터베이스에 직접 저장하고 서버의 디스크 할당량은 매우 작기 때문에 큰 파일을 업로드하면 IOExeption - 디스크 할당량을 초과했습니다.

Spring의 MultiPartResolver가 로컬 파일 시스템에 파일을 저장하기 전에 클라이언트의 들어오는 요청에서 스트림을 직접 가져올 수있는 방법이 있습니까? 그래서 우리는 직접 db로 스트리밍 할 수 있습니까?

해결법

  1. ==============================

    1.https://commons.apache.org/proper/commons-fileupload/streaming.html에서 설명한 것처럼 직접 아파치를 사용할 수 있습니다.

    https://commons.apache.org/proper/commons-fileupload/streaming.html에서 설명한 것처럼 직접 아파치를 사용할 수 있습니다.

    @Controller
    public class UploadController {
    
        @RequestMapping("/upload")
        public String upload(HttpServletRequest request) throws IOException, FileUploadException {
    
            ServletFileUpload upload = new ServletFileUpload();
    
            FileItemIterator iterator = upload.getItemIterator(request);
            while (iterator.hasNext()) {
                FileItemStream item = iterator.next();
    
                if (!item.isFormField()) {
                    InputStream inputStream = item.openStream();
                    //...
                }
            }
        }
    }
    

    스프링 다중 분할 메커니즘을 비활성화하십시오.

    application.yml :

    spring:
       http:
          multipart:
             enabled: false
    
  2. ==============================

    2.사실 그것은 사소한 일이 아닙니다. 클라이언트 오른쪽에서 데이터베이스로 스트림을 쓰려면 수동으로 요청을 처리해야합니다. 이 작업을 더 간단하게 만들 수있는 라이브러리가 있습니다. 그 중 하나는 "Apache Commons FileUpload"입니다. 아주 간단한 예제 아래에서이 라이브러리가 들어오는 multipart / form-data 요청을 어떻게 처리 할 수 ​​있습니까?

    사실 그것은 사소한 일이 아닙니다. 클라이언트 오른쪽에서 데이터베이스로 스트림을 쓰려면 수동으로 요청을 처리해야합니다. 이 작업을 더 간단하게 만들 수있는 라이브러리가 있습니다. 그 중 하나는 "Apache Commons FileUpload"입니다. 아주 간단한 예제 아래에서이 라이브러리가 들어오는 multipart / form-data 요청을 어떻게 처리 할 수 ​​있습니까?

    @Controller
    public class Controller{
    
        @RequestMapping("/upload")
        public String upload(HttpServletRequest request){
    
            String boundary = extractBoundary(request);
    
            try {
                MultipartStream multipartStream = new MultipartStream(request.getInputStream(), 
                    boundary.getBytes(), 1024, null);
                boolean nextPart = multipartStream.skipPreamble();
                while(nextPart) {
                    String header = multipartStream.readHeaders();
    
                    if(header.contains("filename")){
                        //if input is file
                        OutputStream output = createDbOutputStream();
                        multipartStream.readBodyData(output);
                        output.flush();
                        output.close();
                    } else {
                        //if input is not file (text, checkbox etc)
                        ByteArrayOutputStream output = new ByteArrayOutputStream();
                        multipartStream.readBodyData(output);
                        String value = output.toString("utf-8");
                        //... do something with extracted value
                    }
                    nextPart = multipartStream.readBoundary();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }    
        }
    
        private String extractBoundary(HttpServletRequest request) {
            String boundaryHeader = "boundary=";
            int i = request.getContentType().indexOf(boundaryHeader)+
                boundaryHeader.length();
            return request.getContentType().substring(i);
        }    
    }
    

    파일 필드의 헤더는 다음과 같습니다.

    Content-Disposition: form-data; name="fieldName"; filename="fileName.jpg"
    Content-Type: image/jpeg
    

    간단한 필드의 헤더는 다음과 같습니다.

    Content-Disposition: form-data; name="fieldName";
    

    이 스 니펫은 방향을 보여주기 위해 단순화 된 예입니다. 헤더에서 필드 이름을 추출하고 데이터베이스 출력 스트림 등을 생성하는 것과 같은 세부 정보는 없습니다.이 모든 것들을 직접 구현할 수 있습니다. RFC1867에서 찾을 수있는 멀티 파트 요청의 필드 헤더의 예. multipart / form-data RFC2388에 대한 정보.

  3. from https://stackoverflow.com/questions/37870989/spring-how-to-stream-large-multipart-file-uploads-to-database-without-storing by cc-by-sa and MIT license