前幾天發(fā)布了一篇JAVA壓縮文件的文章,今天有朋友跟我說,這壓縮沒啥技術(shù)含量啊,你再弄個壓縮完然后返回前端下載的功能唄。其實吧我覺得下載功能比壓縮更簡單吧,壓縮的遞歸我至少弄了半天才解決。但是朋友有需求,那就搞一下唄。
下載方法有兩種:可以用response.getOutputStream().write()方法,也可以用SpringMVC的ResponseEntity<T>方法。
下載方式也有兩種,一種是先生成壓縮文件放在磁盤上,然后再調(diào)用下載方法,下載完后刪除磁盤中的壓縮文件;另一種方法是將壓縮文件以流的方式傳遞。
代碼比較粗糙,就是想到啥就直接寫下來了,有待優(yōu)化的地方還望大家多多指點
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMApping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@RestController
public class FileToZipDownload {
/**
* 文件壓縮功能
* @param sourcesFiles 源資源,即需要被壓縮的文件
* @param zos 壓縮包
* @param fileName 壓縮包內(nèi)的文件名稱
*/
public void compressFile(File sourcesFiles, ZipOutputStream zos,String fileName) throws IOException {
//1.如果源資源是目錄,先判斷是否空文件夾
if (sourcesFiles.isDirectory()){
File[] files = sourcesFiles.listFiles();
//1-1.先判斷是否空文件夾
if (files.length ==0){
//1-2.空文件夾,則在壓縮包中把目錄加上
zos.putNextEntry(new ZipEntry(fileName + File.separator));
}else {
//1-3.如果不是空文件夾,則遞歸列出里面的文件以及文件夾
for (File file : files) {
//文件名稱以目錄保持好
compressFile(file,zos,fileName + File.separator + file.getName());
}
}
}else {
//將文件放到壓縮文件中,同時保留文件名稱
zos.putNextEntry(new ZipEntry(fileName));
//IO的固化操作,先讀取文件再寫入文件壓縮輸出流中,過程不解釋
FileInputStream inputStream = new FileInputStream(sourcesFiles);
int len;
byte[] bytes = new byte[2048];
while ((len = inputStream.read(bytes)) != -1){
zos.write(bytes,0,len);
}
zos.flush(); //刷新流
zos.closeEntry();
inputStream.close();
}
}
/**
* ResponseEntity繼承了HttpEntity類,
HttpEntity代表一個http請求或者響應(yīng)實體,其內(nèi)部有兩個成員變量:header及body,
代表http請求或響應(yīng)的header及body,其中的body是泛化的,
具體方法可以百度一下
* @return ResponseEntity<byte[]>
* @throws Exception
*/
@GetMapping("/down")
public ResponseEntity<byte[]> fileDownload(){
//將要壓縮的文件夾
File sourceFiles = new File("E:" + File.separator + "hello");
//設(shè)置響應(yīng)頭
HttpHeaders headers = new HttpHeaders();
//第一個參數(shù)name:設(shè)置響應(yīng)方式,其中,attachment是通知瀏覽器以下載的方式打開文件;
//第二個參數(shù)filename:文件下載的名稱
headers.setContentDispositionFormData("attachment",sourceFiles.getName() + ".zip");
//通知瀏覽器以流的形式下載返回文件數(shù)據(jù)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//緩存數(shù)據(jù)輸出流,可轉(zhuǎn)換成byte字節(jié)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//創(chuàng)建壓縮輸出流對象,輸出到緩存數(shù)據(jù)輸出流中,不保存到磁盤上
ZipOutputStream zos = new ZipOutputStream(outputStream);
try {
//調(diào)用壓縮文件的方法
this.compressFile(sourceFiles,zos,sourceFiles.getName());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (zos != null){
//ZipOutputStream壓縮輸出流必須在執(zhí)行壓縮操作后再關(guān)閉
zos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//outputStream.toByteArray(),將緩存數(shù)據(jù)輸出流轉(zhuǎn)成字節(jié),返回前端頁面。
return new ResponseEntity<byte[]>(outputStream.toByteArray(),headers, HttpStatus.OK);
}
}