Ich versuche, eine Datei von einem Spring Boot Rest-Dienst herunterzuladen.
@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);
}
Wenn ich versucht habe, die Datei vom Browser herunterzuladen, wird der Download gestartet, schlägt jedoch immer fehl. Stimmt etwas mit dem Dienst nicht, der dazu führt, dass der Download fehlschlägt?
HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=myDoc.docx");
ResourceHttpMessageConverter
zu Ihrer Liste der HttpMessageConverters hinzugefügt wird. Erstellen Sie eine@Configuration
Klasse, die erweitertWebMvcConfigurerAdapter
, implementieren Sie die configureMessageConverters () -Methode und fügen Sie eineconverters.add(new ResourceHttpMessageConverter());
Zeile hinzuDer folgende Beispielcode hat für mich funktioniert und könnte jemandem helfen.
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); } }
quelle
Ich würde vorschlagen, einen StreamingResponseBody zu verwenden, da die Anwendung damit direkt in die Antwort (OutputStream) schreiben kann, ohne den Servlet-Container-Thread aufzuhalten. Dies ist ein guter Ansatz, wenn Sie eine sehr große Datei herunterladen.
@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); } }; }
Ps.: Bei Verwendung von StreamingResponseBody wird dringend empfohlen, den in Spring MVC verwendeten TaskExecutor für die Ausführung asynchroner Anforderungen zu konfigurieren. TaskExecutor ist eine Schnittstelle, die die Ausführung eines Runnable abstrahiert.
Weitere Informationen: https://medium.com/swlh/streaming-data-with-spring-boot-restful-web-service-87522511c071
quelle
ResponseEntity<Resource>
Lösungen zum Laufen bringen. Diese Lösung hat sofortStreamingResponseBody
funktioniert. DANKE!Ich möchte einen einfachen Ansatz zum Herunterladen von Dateien mit JavaScript (ES6), React und einem Spring Boot- Backend teilen :
Ressource von org.springframework.core.io.Resource
@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); }
Setzen Sie den responseType auf arraybuffer , um den in der Antwort enthaltenen Datentyp anzugeben.
export const DownloadFile = (filename, extraVariable) => { let url = 'http://localhost:8080/files/' + filename + '/' + extraVariable; return axios.get(url, { responseType: 'arraybuffer' }).then((response) => { return response; })};
DownloadFile('filename.extension', 'extraVariable').then( (response) => { fileDownload(response.data, filename); } , (error) => { // ERROR });
quelle
Wenn Sie eine große Datei aus dem Dateisystem des Servers herunterladen müssen, kann ByteArrayResource den gesamten Java-Heap-Speicherplatz belegen . In diesem Fall können Sie FileSystemResource verwenden
quelle
@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); }
Verwenden Sie zum Testen den Postboten
http: // localhost: 8080 / api / downloadfile / GDD / 1.zip
quelle
Die Verwendung von Apache IO könnte eine weitere Option zum Kopieren des Streams sein
@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(); }
Maven-Abhängigkeit
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency>
quelle