前言
一次“上傳文件”的點擊蘊含着一輪請求,我們要做的就是針對每一次的請求進行i/o處理,並返回給前端用戶
一.文件上傳
文件上傳,也稱爲upload,是指將本地圖片、視頻、音頻等文件上傳到服務器上,文件上傳與下載可謂是在生活中應用十分廣泛,一次上傳對應一次請求,後端要做的是如何把這次請求中的文件信息轉存到指定的地址
以上傳圖片爲例
在表單裏,當點擊或者拖拽文件上傳,前端頁面就會發出一次如下的請求:
在後端的Controller層中怎樣才能接受到前端發來的文件呢?這就要用到Apache爲我們提供的兩個組件,commons-fileupload
與commons-io
,本質是對文件的i/o操作
基於上面兩個組件,Spring框架在spring-web包中對文件上傳進行了封裝,大大簡化了服務端代碼,所以只需要在Controller的方法中聲明一個MultipartFile類型的參數即可接收上傳的文件,就像這樣:
public class CommonController {
@Value("${reggie.path}") //@Value註解讀取配置文件中reggie的值
private String Basepath;
@PostMapping("/upload")
public R<String> upload(MultipartFile file) {
//file是一個指定文件,必須轉存到指定位置,這裏的形參必須命名爲file!
log.info(file.toString());
String usedName = file.getOriginalFilename();//原始名
String jpg = usedName.substring(usedName.lastIndexOf("."));
String uuidName = UUID.randomUUID().toString() + jpg;//使用UUID生成32位隨機名
//創建一個目錄對象
File file1 = new File(Basepath);
//如果目錄不存在
if (!(file1.exists())) {
file1.mkdirs();//就按照Basepath創建一個目錄
}
//將臨時文件轉存到電腦硬盤
try {
//通過配置文件的形式將轉存路徑變得更靈活
file.transferTo(new File(Basepath + uuidName));
} catch (IOException e) {
e.printStackTrace();
}
return R.success(uuidName);//把文件名字給前端,回顯數據
}
}
要注意這裏的形參必須定義爲file,與前端中的表單信息一致,否則文件信息不會傳到方法裏。
當在前端頁面上傳文件過後,文件信息就被存到了一個tomcat臨時目錄中,在本地電腦中可以找到
爲了實現完整的上傳功能,需要將臨時的文件轉存到指定的位置中,如果不轉存,下一次刷新文件信息就會丟失file.transferTo(new File(Basepath+usedName));
二.改進
大家可能會發現,usedName就是用戶上傳文件的文件名,但難免會出現重名的情況,爲了避免我們可以使用UUID生成隨機文件名,但是生成的id沒有“.jpg”的的後綴,所以還需要動態地去截取一下usedName,就像這樣:
String usedName= file.getOriginalFilename();//原始名
String jpg = usedName.substring(usedName.lastIndexOf("."));//截取.jpg後綴
String uuidName= UUID.randomUUID().toString()+jpg;//使用UUID生成32位隨機名
在SpringBoot的配置類中,轉存目錄path是我自定義的,這就需要考慮目錄存不存在的問題,對此應在轉存前加上判斷條件,就像這樣:
//創建一個目錄對象
File file1 = new File(Basepath);
//如果目錄不存在
if (!(file1.exists())){
file1.mkdirs();//就按照Basepath創建一個目錄
}
三.文件下載
爲了上傳文件(圖片)後能夠回顯至瀏覽器(上傳後能看到自己上傳的圖片)我們需要對上傳的文件進行讀取、下載,本質是將文件從服務器傳輸到本地計算機的過程,也是文件i/o讀寫的一種體現形式,只不過是從服務器到瀏覽器再到電腦
同樣地,當客戶端點擊下載文件,一次請求就夾帶了文件的id,也就是(uuidName),針對前端傳來的name,在Controller層中要做出相應的i/o處理,做出響應,就像這樣:
@GetMapping("/download")
//請求匹配到方法
public void download(String name, HttpServletResponse response) {
//通過輸入流讀取文件內容
try {
FileInputStream fileInputStream = new FileInputStream(Basepath + name);
//通過輸出流,將文件寫回到瀏覽器,在瀏覽器展示圖片
ServletOutputStream outputStream = response.getOutputStream();
response.setContentType("image/jpg");//設置響應回去的是什麼類型的文件
int length = 0; // i/o讀取 重點複習
byte[] bytes = new byte[1024];
while (((length = fileInputStream.read(bytes)) != -1)) {
outputStream.write(bytes, 0, length);
outputStream.flush();
}
//關閉資源
outputStream.close();
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
四.上傳圖片/回顯圖片
當爲菜品添加其圖示並回顯至瀏覽器,這就涉及到文件上傳下載,文件不下載到瀏覽器就不會回顯!
回顯的過程,不難看出就是通過發送一個name參數傳給後端的download方法並得到響應:
從上傳到回顯其實就是upload/download方法的調用,就像這樣:
@PostMapping("/upload")
public R<String> upload(MultipartFile file) {
//file是一個指定文件,必須轉存到指定位置,這裏的形參必須命名爲file!
log.info(file.toString());
String usedName = file.getOriginalFilename();//原始名
String jpg = usedName.substring(usedName.lastIndexOf("."));
String uuidName = UUID.randomUUID().toString() + jpg;//使用UUID生成32位隨機名
//創建一個目錄對象
File file1 = new File(Basepath);
//如果目錄不存在
if (!(file1.exists())) {
file1.mkdirs();//就按照Basepath創建一個目錄
}
//將臨時文件轉存到電腦硬盤
try {
//通過配置文件的形式將轉存路徑變得更靈活
file.transferTo(new File(Basepath + uuidName));
} catch (IOException e) {
e.printStackTrace();
}
return R.success(uuidName);//把文件名字給前端,回顯數據
}
@GetMapping("/download")
//請求匹配到方法
public void download(String name, HttpServletResponse response) {
//通過輸入流讀取文件內容
try {
FileInputStream fileInputStream = new FileInputStream(new File(Basepath + name));
//通過輸出流,將文件寫回到瀏覽器,在瀏覽器展示圖片
ServletOutputStream outputStream = response.getOutputStream();
response.setContentType("image/jpg");//設置響應回去的是什麼類型的文件
int length = 0; // i/o讀取 重點複習
byte[] bytes = new byte[1024];
while (((length = fileInputStream.read(bytes)) != -1)) {
outputStream.write(bytes, 0, length);
outputStream.flush();
}
//關閉資源
outputStream.close();
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
這樣文件的上傳與下載就get了
轉載:https://www.lmlphp.com/user/414079/article/item/10594072