SpringBootWeb案例05
前面我們已經(jīng)實現(xiàn)了員工信息的條件分頁查詢以及刪除操作。 關(guān)于員工管理的功能,還有兩個需要實現(xiàn)新增和修改員工。
本節(jié)的主要內(nèi)容:
- 文件上傳
2. 文件上傳
在我們完成的新增員工功能中,還存在一個問題:沒有頭像(圖片缺失)
上述問題,需要我們通過文件上傳技術(shù)來解決。下面我們就進入到文件上傳技術(shù)的學習。
文件上傳技術(shù)這塊我們主要講解三個方面:首先我們先對文件上傳做一個整體的介紹,接著再學習文件上傳的本地存儲方式,最后學習云存儲方式。
接下來我們就先來學習下什么是文件上傳。
2.1 簡介
文件上傳,是指將本地圖片、視頻、音頻等文件上傳到服務(wù)器,供其他用戶瀏覽或下載的過程。
文件上傳在項目中應用非常廣泛,我們經(jīng)常發(fā)微博、發(fā)微信朋友圈都用到了文件上傳功能。
在我們的案例中,在新增員工的時候,要上傳員工的頭像,此時就會涉及到文件上傳的功能。在進行文件上傳時,我們點擊加號或者是點擊圖片,就可以選擇手機或者是電腦本地的圖片文件了。當我們選擇了某一個圖片文件之后,這個文件就會上傳到服務(wù)器,從而完成文件上傳的操作。
想要完成文件上傳這個功能需要涉及到兩個部分:
- 前端程序
- 服務(wù)端程序
我們先來看看在前端程序中要完成哪些代碼:
<form action="/upload" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="username"><br>
年齡: <input type="text" name="age"><br>
頭像: <input type="file" name="image"><br>
<input type="submit" value="提交">
</form>
上傳文件的原始form表單,要求表單必須具備以下三點(上傳文件頁面三要素):
-
表單必須有file域,用于選擇要上傳的文件
<input type="file" name="image"/>
-
表單提交方式必須為POST
通常上傳的文件會比較大,所以需要使用 POST 提交方式
-
表單的編碼類型enctype必須要設(shè)置為:multipart/form-data
普通默認的編碼格式是不適合傳輸大型的二進制數(shù)據(jù)的,所以在文件上傳時,表單的編碼格式必須設(shè)置為multipart/form-data
前端頁面的3要素我們了解后,接下來我們就來驗證下所講解的文件上傳3要素。
在提供的"課程資料"中有一個名叫"文件上傳"的文件夾,直接將里的"upload.html"文件,復制到springboot項目工程下的static目錄里面。
下面我們來驗證:刪除form表單中enctype屬性值,會是什么情況?
- 在IDEA中直接使用瀏覽器打開upload.html頁面
- 選擇要上傳的本地文件
- 點擊"提交"按鈕,進入到開發(fā)者模式觀察
我們再來驗證:設(shè)置form表單中enctype屬性值為multipart/form-data,會是什么情況?
<form action="/upload" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="username"><br>
年齡: <input type="text" name="age"><br>
頭像: <input type="file" name="image"><br>
<input type="submit" value="提交">
</form>
知道了前端程序中需要設(shè)置上傳文件頁面三要素,那我們的后端程序又是如何實現(xiàn)的呢?
-
首先在服務(wù)端定義這么一個controller,用來進行文件上傳,然后在controller當中定義一個方法來處理
/upload
請求 -
在定義的方法中接收提交過來的數(shù)據(jù) (方法中的形參名和請求參數(shù)的名字保持一致)
- 用戶名:String name
- 年齡: Integer age
- 文件: MultipartFile image
Spring中提供了一個API:MultipartFile,使用這個API就可以來接收到上傳的文件
問題:如果表單項的名字和方法中形參名不一致,該怎么辦?
public Result upload(String username, Integer age, MultipartFile file) //file形參名和請求參數(shù)名image不一致
解決:使用@RequestParam注解進行參數(shù)綁定
public Result upload(String username, Integer age, @RequestParam("image") MultipartFile file)
UploadController代碼:
@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) {
log.info("文件上傳:{},{},{}",username,age,image);
return Result.success();
}
}
后端程序編寫完成之后,打個斷點,以debug方式啟動SpringBoot項目
打開瀏覽器輸入:http://localhost:8080/upload.html , 錄入數(shù)據(jù)并提交
通過后端程序控制臺可以看到,上傳的文件是存放在一個臨時目錄
打開臨時目錄可以看到以下內(nèi)容:
表單提交的三項數(shù)據(jù)(姓名、年齡、文件),分別存儲在不同的臨時文件中:
當我們程序運行完畢之后,這個臨時文件會自動刪除。
所以,我們?nèi)绻胍獙崿F(xiàn)文件上傳,需要將這個臨時文件,要轉(zhuǎn)存到我們的磁盤目錄中。
2.2 本地存儲
前面我們已分析了文件上傳功能前端和后端的基礎(chǔ)代碼實現(xiàn),文件上傳時在服務(wù)端會產(chǎn)生一個臨時文件,請求響應完成之后,這個臨時文件被自動刪除,并沒有進行保存。下面呢,我們就需要完成將上傳的文件保存在服務(wù)器的本地磁盤上。
代碼實現(xiàn):
- 在服務(wù)器本地磁盤上創(chuàng)建images目錄,用來存儲上傳的文件(例:E盤創(chuàng)建images目錄)
- 使用MultipartFile類提供的API方法,把臨時文件轉(zhuǎn)存到本地磁盤目錄下
MultipartFile 常見方法:
- String getOriginalFilename(); //獲取原始文件名
- void transferTo(File dest); //將接收的文件轉(zhuǎn)存到磁盤文件中
- long getSize(); //獲取文件的大小,單位:字節(jié)
- byte[] getBytes(); //獲取文件內(nèi)容的字節(jié)數(shù)組
- InputStream getInputStream(); //獲取接收到的文件內(nèi)容的輸入流
@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上傳:{},{},{}",username,age,image);
//獲取原始文件名
String originalFilename = image.getOriginalFilename();
//將文件存儲在服務(wù)器的磁盤目錄
image.transferTo(new File("E:/images/"+originalFilename));
return Result.success();
}
}
利用postman測試:
注意:請求參數(shù)名和controller方法形參名保持一致
通過postman測試,我們發(fā)現(xiàn)文件上傳是沒有問題的。但是由于我們是使用原始文件名作為所上傳文件的存儲名字,當我們再次上傳一個名為1.jpg文件時,發(fā)現(xiàn)會把之前已經(jīng)上傳成功的文件覆蓋掉。
解決方案:保證每次上傳文件時文件名都唯一的(使用UUID獲取隨機文件名)
@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上傳:{},{},{}",username,age,image);
//獲取原始文件名
String originalFilename = image.getOriginalFilename();
//構(gòu)建新的文件名
String extname = originalFilename.substring(originalFilename.lastIndexOf("."));//文件擴展名
String newFileName = UUID.randomUUID().toString()+extname;//隨機名+文件擴展名
//將文件存儲在服務(wù)器的磁盤目錄
image.transferTo(new File("E:/images/"+newFileName));
return Result.success();
}
}
在解決了文件名唯一性的問題后,我們再次上傳一個較大的文件(超出1M)時發(fā)現(xiàn),后端程序報錯:
報錯原因呢是因為:在SpringBoot中,文件上傳時默認單個文件最大大小為1M
那么如果需要上傳大文件,可以在application.properties進行如下配置:
#配置單個文件最大上傳大小
spring.servlet.multipart.max-file-size=10MB
#配置單個請求最大上傳大小(一次請求可以上傳多個文件)
spring.servlet.multipart.max-request-size=100MB
到時此,我們文件上傳的本地存儲方式已完成了。但是這種本地存儲方式還存在一問題:
如果直接存儲在服務(wù)器的磁盤目錄中,存在以下缺點:文章來源:http://www.zghlxwxcb.cn/news/detail-834840.html
- 不安全:磁盤如果損壞,所有的文件就會丟失
- 容量有限:如果存儲大量的圖片,磁盤空間有限(磁盤不可能無限制擴容)
- 無法直接訪問
為了解決上述問題呢,通常有兩種解決方案:文章來源地址http://www.zghlxwxcb.cn/news/detail-834840.html
- 自己搭建存儲服務(wù)器,如:fastDFS 、MinIO
- 使用現(xiàn)成的云服務(wù),如:阿里云,騰訊云,華為云
到了這里,關(guān)于【JaveWeb教程】(32)SpringBootWeb案例之《智能學習輔助系統(tǒng)》的詳細實現(xiàn)步驟與代碼示例(5)文件上傳的實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!