Spring Boot Rest 서비스에서 파일 다운로드
Spring Boot Rest 서비스에서 파일을 다운로드하려고 합니다.
@RequestMapping(path="/downloadFile",method=RequestMethod.GET)
@Consumes(MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<InputStreamReader> downloadDocument(
String acquistionId,
String fileType,
Integer expressVfId) throws IOException {
File file2Upload = new File("C:\\Users\\admin\\Desktop\\bkp\\1.rtf");
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
InputStreamReader i = new InputStreamReader(new FileInputStream(file2Upload));
System.out.println("The length of the file is : "+file2Upload.length());
return ResponseEntity.ok().headers(headers).contentLength(file2Upload.length())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(i);
}
브라우저에서 파일을 다운로드하려고 하면 다운로드가 시작되지만 항상 실패합니다.다운로드 실패의 원인이 되는 서비스에 문제가 있습니까?
InputStreamResource를 사용하는 옵션1
지정된 InputStream에 대한 리소스 구현.
다른 특정 리소스 구현이 >에 해당되지 않는 경우에만 사용해야 합니다.특히 가능한 경우 ByteArrayResource 또는 파일 기반 리소스 구현을 선호합니다.
@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity<Resource> download(String param) throws IOException {
// ...
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
InputStreamResource 설명서에서 권장하는 옵션2 - ByteArrayResource 사용:
@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity<Resource> download(String param) throws IOException {
// ...
Path path = Paths.get(file.getAbsolutePath());
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
아래 샘플 코드가 도움이 되어 누군가에게 도움이 될 수 있습니다.
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@RestController
@RequestMapping("/app")
public class ImageResource {
private static final String EXTENSION = ".jpg";
private static final String SERVER_LOCATION = "/server/images";
@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity<Resource> download(@RequestParam("image") String image) throws IOException {
File file = new File(SERVER_LOCATION + File.separator + image + EXTENSION);
HttpHeaders header = new HttpHeaders();
header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=img.jpg");
header.add("Cache-Control", "no-cache, no-store, must-revalidate");
header.add("Pragma", "no-cache");
header.add("Expires", "0");
Path path = Paths.get(file.getAbsolutePath());
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));
return ResponseEntity.ok()
.headers(header)
.contentLength(file.length())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(resource);
}
}
StreamingResponseBody를 사용하면 응용 프로그램이 Servlet 컨테이너 스레드를 유지하지 않고 응답(OutputStream)에 직접 쓸 수 있기 때문에 사용을 권장합니다.대용량 파일을 다운로드하는 경우에는 이 방법이 좋습니다.
@GetMapping("download")
public StreamingResponseBody downloadFile(HttpServletResponse response, @PathVariable Long fileId) {
FileInfo fileInfo = fileService.findFileInfo(fileId);
response.setContentType(fileInfo.getContentType());
response.setHeader(
HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=\"" + fileInfo.getFilename() + "\"");
return outputStream -> {
int bytesRead;
byte[] buffer = new byte[BUFFER_SIZE];
InputStream inputStream = fileInfo.getInputStream();
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
};
}
추신: StreamingResponseBody를 사용하는 경우 비동기 요청을 실행하기 위해 Spring MVC에서 사용되는 TaskExecutor를 설정하는 것이 좋습니다.TaskExecutor는 Runnable 실행을 추상화하는 인터페이스입니다.
상세정보 : https://medium.com/swlh/streaming-data-with-spring-boot-restful-web-service-87522511c071
JavaScript(ES6), React 및 Spring Boot 백엔드를 사용하여 파일을 다운로드하는 간단한 방법을 공유합니다.
- 스프링 부트레스트 컨트롤러
org.springframework.core.io에서 제공하는 리소스.자원
@SneakyThrows
@GetMapping("/files/{filename:.+}/{extraVariable}")
@ResponseBody
public ResponseEntity<Resource> serveFile(@PathVariable String filename, @PathVariable String extraVariable) {
Resource file = storageService.loadAsResource(filename, extraVariable);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
.body(file);
}
responseType을 어레이 버퍼로 설정하여 응답에 포함된 데이터 유형을 지정합니다.
export const DownloadFile = (filename, extraVariable) => {
let url = 'http://localhost:8080/files/' + filename + '/' + extraVariable;
return axios.get(url, { responseType: 'arraybuffer' }).then((response) => {
return response;
})};
마지막 단계 > 다운로드
js-file-download의 도움으로 브라우저가 다운로드된 것처럼 데이터를 파일에 저장할 수 있습니다.
DownloadFile('filename.extension', 'extraVariable').then(
(response) => {
fileDownload(response.data, filename);
}
, (error) => {
// ERROR
});
서버의 파일 시스템에서 대용량 파일을 다운로드해야 하는 경우, 바이트 어레이 리소스는 모든 Java 힙 공간을 차지할 수 있습니다.이 경우 FileSystemResource를 사용할 수 있습니다.
@GetMapping("/downloadfile/{productId}/{fileName}")
public ResponseEntity<Resource> downloadFile(@PathVariable(value = "productId") String productId,
@PathVariable String fileName, HttpServletRequest request) {
// Load file as Resource
Resource resource;
String fileBasePath = "C:\\Users\\v_fzhang\\mobileid\\src\\main\\resources\\data\\Filesdown\\" + productId
+ "\\";
Path path = Paths.get(fileBasePath + fileName);
try {
resource = new UrlResource(path.toUri());
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
// Try to determine file's content type
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
System.out.println("Could not determine file type.");
}
// Fallback to the default content type if type could not be determined
if (contentType == null) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
테스트하려면 우체부를 사용합니다.
http://localhost: 8080/api/downloadfile/GDD/1.zip
Apache IO를 사용하는 것도 스트림을 복사하기 위한 다른 옵션일 수 있습니다.
@RequestMapping(path = "/file/{fileId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> downloadFile(@PathVariable(value="fileId") String fileId,HttpServletResponse response) throws Exception {
InputStream yourInputStream = ...
IOUtils.copy(yourInputStream, response.getOutputStream());
response.flushBuffer();
return ResponseEntity.ok().build();
}
메이브 의존성
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
언급URL : https://stackoverflow.com/questions/35680932/download-a-file-from-spring-boot-rest-service
'itsource' 카테고리의 다른 글
DOM 변경 검출 (0) | 2022.09.24 |
---|---|
날짜별 Panda DataFrames 필터링 (0) | 2022.09.24 |
PHP XML Nice 형식을 출력하는 방법 (0) | 2022.09.24 |
Sublime Text 2에서 Python 코드를 실행하려면 어떻게 해야 하나요? (0) | 2022.09.24 |
is_a와 instance of의 차이점은 무엇입니까? (0) | 2022.09.24 |