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

时间:2016-04-28 08:53:52

标签: java spring spring-mvc

我有一个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没关系)?

3 个答案:

答案 0 :(得分:6)

基于解决方案here(对于普通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
    }        
}

答案 1 :(得分:0)

未经测试,但类似的东西应该有效:

final Path zipTmpPath = Paths.get("C:/file.csv.zip");
final ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipTmpPath, StandardOpenOption.WRITE));
final ZipEntry zipEntry = new ZipEntry("file.csv");
zipOut.putNextEntry(zipEntry);
Path csvPath = Paths.get("C:/file.csv");
List<String> lines = Files.readAllLines(csvPath);
for(String line : lines)
{
    for(char c : line.toCharArray())
    {
        zipOut.write(c);
    }
}
zipOut.flush();
zipOut.close();
return new FileSystemResource("C:/file.csv.zip");

答案 2 :(得分:-3)

使用它:

@RequestMapping(value =“/ zip”,produce =“application / zip”)

这可以解决您的问题