Spring REST - ZIP 파일을 생성하여 클라이언트로 전송
백엔드에서 받은 아카이브된 파일이 들어 있는 ZIP 파일을 만든 다음 이 파일을 사용자에게 보냅니다.이틀째 답을 찾고 있는데 제대로 된 해결책을 찾을 수가 없어요, 아마 당신이 도와주실 수 있을 거예요 :)
현재 코드는 다음과 같습니다(Spring 컨트롤러에서 모든 작업을 수행해서는 안 된다는 것을 알고 있지만, 신경 쓰지 마십시오. 테스트 목적일 뿐입니다. 작동하는 방법을 찾기 위한 것입니다.).
@RequestMapping(value = "/zip")
public byte[] zipFiles(HttpServletResponse response) throws IOException {
// Setting HTTP headers
response.setContentType("application/zip");
response.setStatus(HttpServletResponse.SC_OK);
response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");
// Creating byteArray stream, make it bufferable and passing this buffer 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
파일.
제거할 때.html
내선 및 그냥 남기기test.zip
올바르게 열립니다.그래서 제 질문은 다음과 같습니다.
- 반품을 피하는 방법
.html
연장? - 왜 추가되었습니까?
제가 무엇을 더 할 수 있을지 모르겠습니다.저도 교체하려고 했습니다.ByteArrayOuputStream
다음과 같은 것으로:
OutputStream outputStream = response.getOutputStream();
그리고 메소드를 void로 설정하여 아무것도 반환하지 않지만 생성되었습니다..zip
파일이 손상되었습니까?
컴퓨터를 푼 후 MacBook에서test.zip
나는 받고 있었습니다.test.zip.cpgz
그것은 다시 나에게 주는 것.test.zip
파일 등.
Windows에서 .zip 파일이 손상되어 제가 말한 대로 열리지도 못했습니다.
제 생각에도, 그 제거는.html
자동으로 확장하는 것이 가장 좋은 옵션이 될 것입니다. 하지만 어떻게 해야 할까요?
보이는 것만큼 어렵지 않기를 바랍니다 :)
감사해요.
문제가 해결되었습니다.
대체됨:
response.setContentType("application/zip");
포함:
@RequestMapping(value = "/zip", produces="application/zip")
그리고 이제 난 맑고 아름다운 투명한.zip
파일.
만약 여러분 중에 더 나은 혹은 더 빠른 제안이 있거나 조언을 하고 싶은 사람이 있다면, 저는 궁금해요.
@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();
}
@RequestMapping(value="/zip", produces="application/zip")
public ResponseEntity<StreamingResponseBody> zipFiles() {
return ResponseEntity
.ok()
.header("Content-Disposition", "attachment; filename=\"test.zip\"")
.body(out -> {
var zipOutputStream = new ZipOutputStream(out);
// 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();
});
}
사용 중REST Web Service
의Spring Boot
그리고 나는 엔드포인트가 항상 되돌아오도록 설계했다.ResponseEntity
그것이 그렇든JSON
또는PDF
또는ZIP
그리고 저는 부분적으로 영감을 받은 다음과 같은 해결책을 생각해냈습니다.denov's answer
이 질문과 내가 변환하는 방법을 배운 다른 질문에서.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);
}
}
이제 엔드포인트를 쉽게 복구할 수 있습니다.ResponseEntity<?>
를 사용하여 아래와 같이byte[]
데이터 및 사용자 정의 헤더를 위해 특별히 조정된pdf
또는zip
.
@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
는 단순 불변입니다.POJO
내가 만든 클래스private byte[] data;
그리고.org.springframework.http.HttpHeaders headers;
둘 다 반환하기 위한 필드로data
그리고.headers
실용적인 방법에서.
Spring Boot 응용 프로그램에서 작동한 유일한 기능(하드코딩된 파일 경로 없음!)
@GetMapping(value = "/zip-download", produces="application/zip")
public void zipDownload(@RequestParam List<String> name, HttpServletResponse response) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + zipFileName + "\"");
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
for (String fileName : name) {
// resource content length
int contentLength = 123;
// resource input stream
InputStream stream = InputStream.nullInputStream();
ZipEntry zipEntry = new ZipEntry(fileName);
zipEntry.setSize(contentLength);
zipOut.putNextEntry(zipEntry);
StreamUtils.copy(stream, zipOut);
zipOut.closeEntry();
}
zipOut.finish();
zipOut.close();
}
언급URL : https://stackoverflow.com/questions/27952949/spring-rest-create-zip-file-and-send-it-to-the-client
'programing' 카테고리의 다른 글
데이터베이스의 자격 증명을 어디에 보관해야 합니까? (0) | 2023.09.03 |
---|---|
Node.js의 약속 이해 (0) | 2023.09.03 |
Chrome의 ASP.NET에서 이상한 focus_change nikkomsgchannel 오류가 발생함 (0) | 2023.09.03 |
가져오기 오류: DLL 로드 실패: %1은 올바른 Win32 응용 프로그램이 아닙니다.하지만 DLL은 거기에 있습니다. (0) | 2023.09.03 |
연결을 사용하여 업데이트 후속 처리 (0) | 2023.08.29 |