복붙노트

[SPRING] Spring REST - .zip 파일을 만들어 클라이언트로 보냅니다.

SPRING

Spring REST - .zip 파일을 만들어 클라이언트로 보냅니다.

백 엔드에서받은 압축 파일이 들어있는 .zip 파일을 만든 다음이 파일을 사용자에게 보내고 싶습니다. 2 일 동안 나는 대답을 찾고 있었고 올바른 해결책을 찾지 못했습니다, 어쩌면 당신은 저를 도울 수 있습니다 :)

지금은 코드가 다음과 같습니다. (스프링 컨트롤러에서이 모든 작업을 수행해야한다는 것을 알고 있지만 그 일은 신경 쓰지 않습니다. 테스트 용으로, 작동 방식을 찾는 것입니다)

    @RequestMapping(value = "/zip")
    public byte[] zipFiles(HttpServletResponse response) throws IOException{
        //setting headers
        response.setContentType("application/zip");
        response.setStatus(HttpServletResponse.SC_OK);
        response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");

        //creating byteArray stream, make it bufforable and passing this buffor to ZipOutputStream
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
        ZipOutputStream zipOutputStream = new ZipOutputStream(bufferedOutputStream);

        //simple file list, just for tests
        ArrayList<File> files = new ArrayList<>(2);
        files.add(new File("README.md"));

        //packing files
        for (File file : files) {
            //new zip entry and copying inputstream with file to zipOutputStream, after all closing streams
            zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
            FileInputStream fileInputStream = new FileInputStream(file);

            IOUtils.copy(fileInputStream, zipOutputStream);

            fileInputStream.close();
            zipOutputStream.closeEntry();
        }

        if (zipOutputStream != null) {
            zipOutputStream.finish();
            zipOutputStream.flush();
            IOUtils.closeQuietly(zipOutputStream);
        }
        IOUtils.closeQuietly(bufferedOutputStream);
        IOUtils.closeQuietly(byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }

하지만 문제는 코드를 사용하여 URL을 입력하면 : localhost : 8080 / zip 파일 : test.zip.html 대신 .zip 파일이 생성된다는 것입니다.

나는 내가 무엇을 할 수 있는지 전혀 모른다. ByteArrayOutputStream을 다음과 같이 바꾸려고했습니다.

OutputStream outputStream = response.getOutputStream();

메소드가 무효가되도록 설정하면 아무 것도 반환하지 않지만 손상된 .zip 파일을 생성 했습니까?

내 맥북에 test.zip 압축을 푼 후에 다시 test.zip 파일을주는 등의 test.zip.cpgz를 얻고 있었다.

Windows에서 .zip 파일이 손상되어 손상되었다.

또한 .html 확장명을 자동으로 제거하는 것이 가장 좋은 방법이 될 것이라고 생각하지만 어떻게해야합니까? 그것이 힘들 것 같아 희망이있다 :) 감사합니다 Logged

해결법

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

    1.해결 될 것으로 보인다. 나는 바꿨다.

    해결 될 것으로 보인다. 나는 바꿨다.

    response.setContentType("application/zip");
    

    와:

    @RequestMapping(value = "/zip", produces="application/zip")
    

    그리고 지금 나는 명확하고 아름다운 .zip 파일을 얻는다. :)

    당신 중 누구라도 더 훌륭하거나 더 빠른 명제를 갖고 있거나 약간의 충고를 원한다면, 계속 진행하십시오. 나는 호기심이 있습니다.

  2. ==============================

    2.

    @RequestMapping(value="/zip", produces="application/zip")
    public void zipFiles(HttpServletResponse response) throws IOException {
    
        //setting headers  
        response.setStatus(HttpServletResponse.SC_OK);
        response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");
    
        ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());
    
        // create a list to add files to be zipped
        ArrayList<File> files = new ArrayList<>(2);
        files.add(new File("README.md"));
    
        // package files
        for (File file : files) {
            //new zip entry and copying inputstream with file to zipOutputStream, after all closing streams
            zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
            FileInputStream fileInputStream = new FileInputStream(file);
    
            IOUtils.copy(fileInputStream, zipOutputStream);
    
            fileInputStream.close();
            zipOutputStream.closeEntry();
        }    
    
        zipOutputStream.close();
    }
    
  3. ==============================

    3.나는 Spring Boot의 REST Web Service를 사용하고 있으며 JSON이든 PDF 또는 ZIP이든 관계없이 항상 ResponseEntity를 반환하도록 끝점을 설계했다.이 질문에 denov의 대답과 다른 질문에서 부분적으로 영감을받은 다음 솔루션을 생각해 냈다. ZipOutputStream을 byte []로 변환하여 ResponseEntity에 엔드 포인트의 출력으로 공급하는 방법을 배웠습니다.

    나는 Spring Boot의 REST Web Service를 사용하고 있으며 JSON이든 PDF 또는 ZIP이든 관계없이 항상 ResponseEntity를 반환하도록 끝점을 설계했다.이 질문에 denov의 대답과 다른 질문에서 부분적으로 영감을받은 다음 솔루션을 생각해 냈다. ZipOutputStream을 byte []로 변환하여 ResponseEntity에 엔드 포인트의 출력으로 공급하는 방법을 배웠습니다.

    어쨌든, 나는 pdf 및 zip 파일 다운로드를위한 두 가지 방법으로 간단한 유틸리티 클래스를 만들었습니다.

    @Component
    public class FileUtil {
        public BinaryOutputWrapper prepDownloadAsPDF(String filename) throws IOException {
            Path fileLocation = Paths.get(filename);
            byte[] data = Files.readAllBytes(fileLocation);
    
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/pdf"));
            String outputFilename = "output.pdf";
            headers.setContentDispositionFormData(outputFilename, outputFilename);
            headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
    
            return new BinaryOutputWrapper(data, headers); 
        }
    
        public BinaryOutputWrapper prepDownloadAsZIP(List<String> filenames) throws IOException {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/zip"));
            String outputFilename = "output.zip";
            headers.setContentDispositionFormData(outputFilename, outputFilename);
            headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
    
            ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
            ZipOutputStream zipOutputStream = new ZipOutputStream(byteOutputStream);
    
            for(String filename: filenames) {
                File file = new File(filename); 
                zipOutputStream.putNextEntry(new ZipEntry(filename));           
                FileInputStream fileInputStream = new FileInputStream(file);
                IOUtils.copy(fileInputStream, zipOutputStream);
                fileInputStream.close();
                zipOutputStream.closeEntry();
            }           
            zipOutputStream.close();
            return new BinaryOutputWrapper(byteOutputStream.toByteArray(), headers); 
        }
    }
    

    이제 끝점은 byte [] 데이터와 pdf 또는 zip에 맞게 특수화 된 사용자 정의 헤더를 사용하여 아래에 표시된 것처럼 ResponseEntity 를 쉽게 반환 할 수 있습니다.

    @GetMapping("/somepath/pdf")
    public ResponseEntity<?> generatePDF() {
        BinaryOutputWrapper output = new BinaryOutputWrapper(); 
        try {
            String inputFile = "sample.pdf"; 
            output = fileUtil.prepDownloadAsPDF(inputFile);
            //or invoke prepDownloadAsZIP(...) with a list of filenames
        } catch (IOException e) {
            e.printStackTrace();
            //Do something when exception is thrown
        } 
        return new ResponseEntity<>(output.getData(), output.getHeaders(), HttpStatus.OK); 
    }
    

    BinaryOutputWrapper는 private byte [] 데이터로 만든 간단한 불변 POJO 클래스입니다. 및 org.springframework.http.HttpHeaders 헤더; 유틸리티 메서드에서 데이터와 헤더를 모두 반환하기 위해 필드로 사용합니다.

  4. from https://stackoverflow.com/questions/27952949/spring-rest-create-zip-file-and-send-it-to-the-client by cc-by-sa and MIT license