1. 程式人生 > 其它 >補充SpringMVC的檔案上傳以及檔案下載

補充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中編寫我們將要進行的操作:

 /**
    * 檔案下載
    */
   @RequestMapping("/download")
   @ResponseBody
   public Map<String, Object> download(String filename,HttpServletResponse response) {
       System.out.println(filename);
       //定義一個返回值
       HashMap<String, Object> map = new HashMap();
//       指定提供資源的磁碟的目錄
       String dir="F:\\Typora檔案\\SpringBoot\\img\\";
//       拼接該檔案地址-判定該檔案是否存在
       File file = new File(dir + filename);
//進行判斷是否存在
       if (file.exists()){
//           存在--讀取檔案--響應檔案--關閉流
           try {
//           建立輸入流物件--讀取磁碟檔案
               InputStream inputStream = new FileInputStream(file);
//             建立一個獲取檔案輸出流物件 可以看成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);
              }
//               關閉流
               outputStream.close();
               inputStream.close();
          } catch (FileNotFoundException e) {
               e.printStackTrace();
          } catch (IOException e) {
               e.printStackTrace();
          }
      }else {
//           如果檔案不存--響應改檔案不存在
           map.put("msg", "檔案下載失敗--檔案不存在");
      }
       return map;
  }

 

而在連結中我們給了定了資源為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);
              }

 

遇到的問題

  1. 使用restful風格無法獲取到我們我們所需的資源。 在路徑上我們無法去讀取<a href="/download/dsb.jpg">資源下載</a>到dsb.jpg的檔案,會報一個406的錯誤。

  2. 獲取資源型別的格式。

//                檔案型別
               response.setHeader("Content-Type","application/jpeg");

這裡jpg格式的一般來說是要在找到相應的格式去進行下載,找到一個資源是:image/jpeg 使用這個格式。