2016-04-28 101 views
1

我有一個servlet,它提供了一個CSV文件下載:如何通過spring @RestController提供壓縮下載的文件?

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

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

這一切正常。

問:我怎樣才能提供這個文件作爲壓縮文件? (zip,gzip,焦油無所謂)?

+0

是否要在服務器上創建zip文件或在webserver和客戶端瀏覽器之間使用「實時gzip壓縮」? – reto

+0

我想創建一個壓縮文件(來自未壓縮的本地文件)。如果它是'zip'或'gzip'並不重要。 – membersound

+0

請參閱http://stackoverflow.com/questions/26113345/compress-dynamic-content-to-servletoutputstream。同樣的技巧可以用普通的控制器。 –

回答

1

基於解決方案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 
    }   
} 

您基於響應OutputStream(你可以簡單地已經注入法)創建一個ZipOutputStream。然後爲壓縮的流創建一個條目並寫入它。

而不是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 
    }   
} 
+0

該方法的返回類型是什麼? 'ZipOutputStream'? 'GZIPOutputStream'可以做到這一點嗎? – membersound

+0

我試着'返回zippedOUt',但給了我:'java.lang.IllegalArgumentException:找不到類型爲:java.util.zip.ZipOutputStream類的返回值的轉換器。當添加'produce =「application/zip」'時,它會導致'org.springframework.web.HttpMediaTypeNotAcceptableException:找不到可接受的表示法。 – membersound

+0

不會有任何回報......因此,「空白」,我寫這樣的理由! –

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"); 
+0

我認爲可以有一個更簡單的方法,而不僅僅是創建一個額外的本地文件。例如,返回一個csv文件很簡單,就像用Spring返回'FileSystemResource'一樣。認爲可能還有壓縮的東西。 ot:雖然不是11k,但我有27點金幣) – membersound

+0

哦......對不起,我的錯誤。 – specializt

-3

使用這樣的:

@RequestMapping(值= 「/壓縮」,產生= 「應用程序/壓縮」)

這可能解決您的問題

+1

...爲什麼人人都會突然想到春天是一個無魔力超級大國的無腦框架? Spring不會自動壓縮 - **可能**是某種插件或特殊配置,但是...... – specializt