当前位置: 首页 > 知识库问答 >
问题:

从Spring开机Rest服务下载文件

曹子平
2023-03-14

我正在尝试从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);
        }

当我试图从浏览器下载文件时,它会启动下载,但总是失败。该服务是否存在导致下载失败的问题?

共有3个答案

微生承业
2023-03-14

我建议使用StreamingResponseBody,因为有了它,应用程序可以直接写入响应(OutputStream),而无需占用Servlet容器线程。如果你正在下载一个非常大的文件,这是一个很好的方法。

@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是一个抽象可运行程序执行的接口。

更多信息:https://medium.com/swlh/streaming-data-with-spring-boot-restful-web-service-87522511c071

孔磊
2023-03-14

下面的示例代码对我有用,可能会对某人有所帮助。

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);
    }

}
濮波
2023-03-14

选项1使用输入流资源

给定InputStream的资源实现。

只有当没有其他特定的资源实现时才应该使用

@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);
}

选项2如InputStreamResource的文档所示,使用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);
}
 类似资料:
  • 问题内容: 我正在尝试从Spring Boot Rest服务下载文件。 当我尝试从浏览器下载文件时,它开始下载,但始终失败。服务有什么问题导致下载失败? 问题答案: 仅当没有其他特定的资源实现适用时才应使用。特别是,尽可能选择ByteArrayResource或任何基于文件的Resource实现。 Option2作为InputStreamResource的文档建议-使用ByteArrayResou

  • 问题内容: 我有一个REST服务,可以向我发送一个较大的ISO文件,REST服务中没有任何问题。现在,我编写了一个Web应用程序,该应用程序调用其余服务以获取文件,在客户端(Web应用程序)端,我收到内存不足异常。下面是我的代码 我在第7行收到内存不足异常,我想我将不得不缓冲并分担一部分,但不知道如何从服务器获取此文件,文件大小约为500至700 MB。谁能帮忙。 异常堆栈: 我的服务器端REST

  • 运行良好的服务器端REST服务代码是

  • 我试图使用JAX-RS从REST服务下载一个文件。这是我的代码,它通过发送GET请求调用下载: 然而,我面临着将响应转换为实际文件对象的问题。所以我所做的是以下几点: 创建的文件无效,我调试了代码并注意到输出包含一个类似的字符串(大得多): Superstore.TWB YSI 7 D M 3 F 编辑:引用关于HTTP响应的REST API引用: 反应体 以下内容之一,具体取决于工作簿的格式:

  • 问题内容: 我有一个URL,用于保存我的工作中的一些项目,它们大部分是MDB文件,但也有一些JPG和PDF。 我需要做的是列出该目录中的每个文件(已完成)并为用户提供下载它的选项。 使用PHP如何实现? 问题答案: 要读取目录内容,可以使用readdir()并使用脚本(在我的示例中)来下载文件 在其中,您可以强制浏览器发送下载数据,并使用basename()来确保客户端不会传递其他文件名,例如

  • 我想从网站上下载一份PDF。PDF需要在代码中生成,我认为这是freemarker和像iText这样的PDF生成框架的组合。还有更好的办法吗? 然而,主要的问题是,我不知道如何允许用户通过Spring控制器下载文件?