簡體   English   中英

春季:從REST控制器下載文件

[英]Spring : Download file from REST controller

我在一個Spring項目中工作,以制作一個Web應用程序,因此有一個Tomcat服務器可以讓我在Web應用程序中吃午餐。
我在這個Web應用程序上有2個功能,第一個功能是允許我在Postgresql數據庫上上傳文件(它可以正常工作)。 但是之后,我希望能夠下載該文件。

這是我的服務方式。

public byte[] download(Integer id){
    Line line = getById(Line.class, id);
    int blobLenght;
    byte[] fileToReturn = null;
    Blob file = line.getFile();
    blobLenght = (int)file.length();
    fileToReturn = file.getBytes(1,blobLenght);
    return fileToReturn;
}

在我的RestController上,我有一個帶有注釋@RequestMapping的方法。 並且此方法返回一個ResponseEntity。 在之后的方法中,將LineService注入(@Autowired)在我的類的頂部。

@RequestMapping(value = "/download", method = RequestMethod.GET)
public ResponseEntity<?> download(@RequestParam("id" Integer id)
{
    byte[] fileToDownload = lineService.download(id);
    return new ResponseEntity<byte[]>(fileToDownload,HttpStatus.OK);
}

我已盡力簡化該方法。

這是我的問題。 確實,我實現了一種方法,該方法可以在我一個接一個地提出一些請求時起作用。 但是,服務器必須能夠支持同時接收很多請求。 現在,當我同時測試許多請求時,我遇到了OutOfMemoryError:Java堆空間。
我嘗試在“下載”方法上實現Stream,但遇到相同的錯誤。 我對流的實現無法很好地完成。 我嘗試了許多在Internet上找到的解決方案,這是我實現的最后一個解決方案:

public ResponseEntity<byte[]> download(Integer id){
    Line line = getById(Line.class, id);
    HttpHeaders headers = new HttpHeaders();
    InputStream is = line.getFile().getBinaryStream;
    byte[] fileToReturn = IOUtils.toByteArray(is);
    headers.setCacheControl(CacheControl.noCache().getHeaderValue());
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(fileToDownload,HttpStatus.OK);
    return responseEntity;
}

您知道我如何更新程序以根據項目的要求進行回答嗎?
如果我行事順心,您能否告訴我我的錯誤在哪里,或者您有什么建議嗎?

謝謝您的幫助!

下午。

我希望我能幫助你。 為我工作。

import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.springframework.core.io.Resource;

@RestController
public class SomeClass{


    @GetMapping("/{fileName}")
    public ResponseEntity<Resource> getFile(@PathVariable String fileName, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Resource file = getFileAsResource(fileName);
        HttpHeaders headers = prepareHeaderForFileReturn(fileName, request, response);
        return new ResponseEntity<Resource>(file, headers, HttpStatus.OK);
    }

    private HttpHeaders prepareHeaderForFileReturn(String fileName, HttpServletRequest request,
                                                   HttpServletResponse response) {
        HttpHeaders headers = new HttpHeaders();
        headers.set(HttpHeaders.CONTENT_TYPE, getContentTypeForAttachment(fileName));
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        return headers;
    }


    public Resource getFileAsResource(String filename) throws FileNotFoundException {
        String filePath = path +  "/" + filename;
        Resource file = loadAsResource(filePath);
        return file;
    }

    private Resource loadAsResource(String filename) throws FileNotFoundException {
        try {
            Path file = Paths.get(filename);
            org.springframework.core.io.Resource resource = new UrlResource(file.toUri());
            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                log.error("Could not read file: " + filename);
                throw new FileNotFoundException();
            }
        } catch (MalformedURLException e) {
            log.error("Could not read file: " + filename, e);
            throw new FileNotFoundException();
        }
    }

    //Obtains a content type for file by his extension.

    public String getContentTypeForAttachment(String fileName) {
        String fileExtension = com.google.common.io.Files.getFileExtension(fileName);
        if (fileExtension.equals("pdf")) return "application/pdf";
        else if (fileExtension.equals("doc")) return "application/msword";
        else if (fileExtension.equals("jpeg")) return "image/jpeg";

    }
}

我用流修改了“下載”方法,它可以像我想要的那樣正常工作。

public void download(Integer id, HttpServletResponse response){
    Line line = getById(Line.class, id);
    InputStream is = line.getFile().getBinaryStream;
    IOUtils.copy(is, response.getOutputStream());
    response.flushBuffer();
}

我的控制器就是這樣的:

public ResponseEntity<?> download(@RequestParam("id") Integer id, HttpServletResponse response)
{
    lineService.download(id,response);
    return new ResponseEntity<>(HttpStatus.OK);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM