如何通过spring @RestController提供压缩下载的文件?


问题内容

我有一个servlet,提供CSV下载文件:

@RestController 
@RequestMapping("/")
public class FileController {

    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public FileSystemResource getFile() {
        return new FileSystemResource("c:\file.csv"); 
    }
}

这样很好。

问题:我如何提供此文件作为压缩文件?(zip,gzip,tar没关系)?


问题答案:

基于此处的解决方案(对于Plain Servlet),您也可以对基于Spring MVC的控制器执行相同的操作。

@RequestMapping(value = "/export", method = RequestMethod.GET)
public void getFile(OutputStream out) {
    FileSystemResource resource = new FileSystemResource("c:\file.csv"); 
    try (ZipOutputStream zippedOut = new ZipOutputStream(out)) {
        ZipEntry e = new ZipEntry(resource.getName());
        // Configure the zip entry, the properties of the file
        e.setSize(resource.contentLength());
        e.setTime(System.currentTimeMillis());
        // etc.
        zippedOut.putNextEntry(e);
        // And the content of the resource:
        StreamUtils.copy(resource.getInputStream(), zippedOut);
        zippedOut.closeEntry();
        zippedOut.finish();
    } catch (Exception e) {
        // Do something with Exception
    }        
}

ZipOutputStream基于响应创建了一个OutputStream(您可以简单地将其注入到方法中)。然后为压缩后的流创建一个条目并将其写入。

除了,OutputStream您还可以连接,HttpServletResponse以便您可以设置文件名和内容类型。

@RequestMapping(value = "/export", method = RequestMethod.GET)
public void getFile(HttpServletResponse response) {
    FileSystemResource resource = new FileSystemResource("c:\file.csv"); 
    response.setContentType("application/zip");
    response.setHeader("Content-Disposition", "attachment; filename=file.zip");

    try (ZipOutputStream zippedOut = new ZipOutputStream(response.getOutputStream())) {
        ZipEntry e = new ZipEntry(resource.getName());
        // Configure the zip entry, the properties of the file
        e.setSize(resource.contentLength());
        e.setTime(System.currentTimeMillis());
        // etc.
        zippedOut.putNextEntry(e);
        // And the content of the resource:
        StreamUtils.copy(resource.getInputStream(), zippedOut);
        zippedOut.closeEntry();
        zippedOut.finish();
    } catch (Exception e) {
        // Do something with Exception
    }        
}