補充SpringMVC的檔案上傳以及檔案下載
SpringMVC之檔案上傳以及檔案下載
頁面:
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="text" name="fName">
<input type="file" name="myFile">
<input type="submit" value="提交">
</form>
檔案上傳必備屬性
enctype="multipart/form-data"
controller:
/**
* 檔案上傳
*/
@RequestMapping("/upload")
@ResponseBody
public Map<String, Object> upload(String fName, MultipartFile myFile) {
//定義一個返回值
HashMap<String, Object> map = new HashMap();
try {
//1.獲取檔案輸入流
System.out.println(fName);
System.out.println(myFile);
InputStream is = myFile.getInputStream();
System.out.println(is);
String url = "F:\\Typora檔案\\upload\\";
File file = new File(url + myFile.getOriginalFilename());
//檔案輸出流
OutputStream os = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
//檔案邊讀邊寫
while ((len = is.read(bytes)) != -1) {
os.write(bytes);
}
//檔案關閉流
os.close();
is.close();
//如果成功儲存檔案資訊就返回一個成功的msg
map.put("msg", "儲存成功");
} catch (IOException e) {
e.printStackTrace();
//如果出現異常情況就返回一個失敗的msg
map.put("msg", "儲存失敗");
}
return map;
}
檔案上傳思路:
在服務端上傳檔案,是以檔案流的形式進行的,所以得先獲取檔案的輸入流(is),有了輸入流就會有個輸出流(os),輸出流針對的引數那就是一個檔案,所以我們得先new File檔案。由於檔案上傳到客戶端在磁碟中進行儲存,而我們PC電腦既充當客戶端,也充當服務端,所以我們可以在桌面建立一個資料夾,複製它的絕對路徑url,然而我們上面new Flie檔案的引數需要確定上傳的檔案的全路徑,我們上傳的所有形式的檔案的全路徑都基於我們桌面新建檔案的url地址+上傳檔案的檔名+字尾,所以在new Flie物件中的引數為
url+myflie.getOriginalFilename
,後面的myflie.getOriginalFilename()方法可以直接獲取到上傳檔案的檔名+字尾
。最後我們對輸出的檔案進行邊讀邊寫的操作,因為不知道我們上傳的檔案需要進行幾次讀寫操作所以使用while迴圈,呼叫is.read()方法讀取一個檔案容器的位元組大小
,每讀一次就會返回一個長度值,只有長度不為-1
就會一直讀下去知道長度為-1
,然後讀一次就執行一次寫檔案的操作os.write(定義的檔案容器的位元組大小)
。
檔案下載過程
我們在頁面上指定下載資源<a href="/download?filename=dsb.jpg">資源下載</a>
後,還需要再Controller中編寫我們將要進行的操作:
/**
* 檔案下載
*/
而在連結中我們給了定了資源為dsb.jpg,我們在Controller中獲取到後,還需要進行指定這個圖片資源的位置在哪裡。
// 建立輸入流物件--讀取磁碟檔案
InputStream inputStream = new FileInputStream(file);
在指定完後,我們還需要進行判斷檔案資源是否存在。
// 指定提供資源的磁碟的目錄
String dir="F:\\Typora檔案\\SpringBoot\\img\\";
// 拼接該檔案地址-判定該檔案是否存在
File file = new File(dir + filename);
//進行判斷是否存在
if (file.exists()){
....
}
在判斷完成後若是存在,需要去讀取磁碟中的檔案,建立一個檔案輸出流。
// 建立一個獲取檔案輸出流物件 可以看成FileOutputStream
ServletOutputStream outputStream = response.getOutputStream();
同時我們還需要返回響應頭的,讓瀏覽器可以返回下載框,並給其設定下載檔案的名稱:
// 指定檔案的名稱
response.setHeader("Content-Disposition","filename="+filename);
// 檔案型別
response.setHeader("Content-Type","application/jpeg");
然後在讀取下載資源並寫入檔案
//讀取過程
byte []bytes=new byte[2048];
int len=0;
while ((len=inputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
遇到的問題
-
使用restful風格無法獲取到我們我們所需的資源。 在路徑上我們無法去讀取
<a href="/download/dsb.jpg">資源下載</a>
到dsb.jpg的檔案,會報一個406的錯誤。 -
獲取資源型別的格式。
// 檔案型別
response.setHeader("Content-Type","application/jpeg");
這裡jpg格式的一般來說是要在找到相應的格式去進行下載,找到一個資源是:image/jpeg 使用這個格式。