Vue+ElementUI+SpringMVC实现图片上传和回显
Vue+ElementUI+SpringMVC實現圖片上傳和table回顯
在之前我們已經講過了 Vue+ElementUI+SpringMVC實現分頁 。
而我們也常遇到表單中包含圖片上傳的需求,并且需要在table中顯示圖片,所以這里我就講一下結合后端的SpringMVC框架如何實現圖片上傳并提交到表單中,在table表格中回顯照片。
本案例對應的開源項目地址請看我的GitHub倉庫:
-
優雅的入門SpringBoot+Mybatis,實現簡單的CRUD
-
優雅的實現電商項目中搜索功能,整合SSM+Redis+Shiro+Solr框架,教你使用Vue+ElementUI寫一個炫酷的后端頁面
寫在前面
本篇博文主要講Vue.js+ElementUI如何實現圖片上傳和提交表單,前端技術會講多一點,因此:
- 如果你對SpringMVC文件上傳和下載不是很清楚,請查看我這篇博文: SpringMVC實現文件上傳和下載
- 因為案例基于SSM框架,如果你你對SSM框架不是很清楚,請查看我這篇博文:SSM框架整合 GitHub
準備
首先,請一定閱讀一下我的 SpringMVC實現文件上傳和下載 本篇博文將不在詳細講這部分內容。
前端:
你會用到以下技術:
Vue.js
Vue-resource.js
ElementUI
我們將實現的效果是什么呢?
圖片上傳:
table展示:
思路分析
想要實現圖片上傳和table的回顯,讓我們先分析以下實現思路:
圖片上傳和表單提交
那么你就要明白圖片上傳和表單提交是兩個功能,其對應不同的接口,表單中并不是保存了這個圖片,而僅僅是保存了儲存圖片的路徑地址。我們需要分析以下幾點:
1、圖片如何上傳,什么時候上傳?
圖片應該在點擊upload上傳組件的時候就觸發了對應的事件,當選擇了要上傳的圖片,點擊確定的時候就請求了后端的接口保存了圖片。也就是說你在瀏覽器中彈出的選擇框中選擇了要上傳的圖片,當你點擊確定的一瞬間就已將圖片保存到了服務器上;而再點擊提交表單的時候,儲存在表單中的圖片數據僅僅是剛才上傳的圖片存儲地址。
2、如何獲取到已經上傳的圖片的儲存地址?
因為在瀏覽器上傳選擇框被確定選擇的瞬間已經請求了后端接口保存了圖片,我們該怎么知道圖片在哪里儲存呢?
- 前端: 比如我們使用了ElementUI提供的上傳組件,其就存在一個上傳成功的回調函數:on-success,這個回調函數被觸發的時間點就是圖片成功上傳后的瞬間,我們就是要在這個回調函數觸發的時候獲取到圖片儲存的地址。
- 后端: 上面講了獲取地址,這個地址就是后端返回給前端的數據(JSON格式)。因為后端圖片上傳接口配置圖片儲存的地址,如果圖片上傳成功,就將圖片儲存的地址以JSON格式返回給前端。
3、如何提交表單
說如何提交表單,這就顯得很簡單了,因為上面我們已經完成了:1、圖片成功上傳;2、獲取到了圖片在服務器上的儲存地址。利用Vue的雙向綁定思想,在圖片成功上傳的回調函數on-success中獲取到后端返回的圖片儲存地址,將這個地址賦值給Vue實例data(){}中定義的表單對象。這樣在提交表單的時候僅需要將這個表單對象發送給后端,保存到數據庫就行了。
圖片在table的回顯
想要將圖片回顯到table表格中其實很簡單,前提只要你在數據庫中保存了正確的圖片儲存地址;在table表格中我們僅需要在<td>列中新定義一列<td><img src="圖片的地址"/></td>即可完成圖片回顯。渲染table數據的時候循環給<img>中的src賦值數據庫中保存的圖片url即可。
后端實現
圖片上傳接口
注意: 關于SpringMVC如何實現文件上傳和下載,請看我的博文: SpringMVC實現文件上傳和下載 。這里我給出代碼,就不再解釋了(#.#):
這里我將文件上傳和下載接口單獨抽離在一個Controller類中:
import com.instrument.entity.Result;@RestController public class UploadDownController {/*** 文件上傳* @param picture* @param request* @return*/@RequestMapping("/upload")public Result upload(@RequestParam("picture") MultipartFile picture, HttpServletRequest request) {//獲取文件在服務器的儲存位置String path = request.getSession().getServletContext().getRealPath("/upload");File filePath = new File(path);System.out.println("文件的保存路徑:" + path);if (!filePath.exists() && !filePath.isDirectory()) {System.out.println("目錄不存在,創建目錄:" + filePath);filePath.mkdir();}//獲取原始文件名稱(包含格式)String originalFileName = picture.getOriginalFilename();System.out.println("原始文件名稱:" + originalFileName);//獲取文件類型,以最后一個`.`為標識String type = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);System.out.println("文件類型:" + type);//獲取文件名稱(不包含格式)String name = originalFileName.substring(0, originalFileName.lastIndexOf("."));//設置文件新名稱: 當前時間+文件名稱(不包含格式)Date d = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String date = sdf.format(d);String fileName = date + name + "." + type;System.out.println("新文件名稱:" + fileName);//在指定路徑下創建一個文件File targetFile = new File(path, fileName);//將文件保存到服務器指定位置try {picture.transferTo(targetFile);System.out.println("上傳成功");//將文件在服務器的存儲路徑返回return new Result(true,"/upload/" + fileName);} catch (IOException e) {System.out.println("上傳失敗");e.printStackTrace();return new Result(false, "上傳失敗");}} }為什么返回一個Result數據類型?
注意這個Result是我自己聲明的一個實體類,用于封裝返回的結果信息,配合@RestController注解實現將封裝的信息以JSON格式return給前端,最后看下我定義的Result:
public class Result implements Serializable {//判斷結果private boolean success;//返回信息private String message;public Result(boolean success, String message) {this.success = success;this.message = message;}public boolean isSuccess() {return success;}setter/getter... }表單提交接口
表單提交大家都比較熟悉了,配合圖片上傳,僅僅是在實體類中多了一個字段存放圖片的URL地址:
@RestController @RequestMapping("/instrument") public class InstrumentController {//注入@Autowiredprivate InstrumentService instrumentService;/*** 添加** @param instrument* @return*/@RequestMapping("/save")public Result save(Instrument instrument) {if(instrument != null){try{instrumentService.save(instrument);return new Result(true,"添加成功");}catch (Exception e){e.printStackTrace();}}return new Result(false, "發生未知錯誤");} }如上
大家可能會疑惑這個為什么返回Result類型的數據? 答:為了前端方便判斷接口執行成功與否。因為我前端使用的是HTML頁面,想要從后端域對象中取數據顯然就有點不現實了。
我寫Controller的時候定義了全局的@RestController注解,和@Controller注解的區別是,前者多了@ResponseBody注解,這樣整合Controller類返回的數據都將給自動轉換成JSON格式。
前端實現
實現圖片上傳
這里我使用了ElementUI的文件上傳組件: 官方文檔
配合ElementUI的上傳組件,我們會這樣定義(這是form表單中的一部分):
<el-form-item label="圖片"><el-uploadref="upload"action="/upload.do"name="picture"list-type="picture-card":limit="1":file-list="fileList":on-exceed="onExceed":before-upload="beforeUpload":on-preview="handlePreview":on-success="handleSuccess":on-remove="handleRemove"><i class="el-icon-plus"></i></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt=""></el-dialog> </el-form-item>注意,我這里僅展示了文件上傳的form-item,ElementUI的表單聲明是:<el-form> 注意 表單中不需要指定enctype="multipart/form-data"這個參數,與我們普通的文件上傳表單是不同的。
了解幾個參數:
-
ref ref是Vue原生參數,用來給組件注冊引用信息。引用信息將會注冊到父組件的$refs對象上,如果定義在普通的DOM元素上,那么$refs指向的就是DOM元素。
-
action action表示此上傳組件對應的上傳接口,此時我們使用的是后端Controller定義的接口
-
name name表示當前組件上傳的文件字段名,需要和后端的上傳接口字段名相同 。
-
list-type 文件列表的類型,主要是文件列表的樣式定義。這里是卡片化。
-
:limit 最大允許上傳的文件個數。
-
file-list 上傳的文件列表,這個參數用于在這個上傳組件中回顯圖片,包含兩個參數:name、url如果你想在這個文件上傳組件中咱叔圖片,賦值對應的參數即可顯示,比如更新數據時,其表單樣式完全和添加表單是相同的。但是table中回顯圖片是完全不需要用這個方式的。
-
:on-exceed 上傳文件超出個數時的鉤子函數。
-
:before-upload 上傳文件前的鉤子函數,參數為上傳的文件,返回false,就停止上傳。
-
:on-preview 點擊文件列表中已上傳的文件時的鉤子函數
-
:on-success 文件上傳成功的鉤子函數
-
:on-remove 文件列表移除時的鉤子函數
-
:src 圖片上傳的URL。
JS部分
//設置全局表單提交格式 Vue.http.options.emulateJSON = true;new Vue({el: '#app',data(){return{//文件上傳的參數dialogImageUrl: '',dialogVisible: false,//圖片列表(用于在上傳組件中回顯圖片)fileList: [{name: '', url: ''}],}},methods(){//文件上傳成功的鉤子函數handleSuccess(res, file) {this.$message({type: 'info',message: '圖片上傳成功',duration: 6000});if (file.response.success) {this.editor.picture = file.response.message; //將返回的文件儲存路徑賦值picture字段}},//刪除文件之前的鉤子函數handleRemove(file, fileList) {this.$message({type: 'info',message: '已刪除原有圖片',duration: 6000});},//點擊列表中已上傳的文件事的鉤子函數handlePreview(file) {},//上傳的文件個數超出設定時觸發的函數onExceed(files, fileList) {this.$message({type: 'info',message: '最多只能上傳一個圖片',duration: 6000});},//文件上傳前的前的鉤子函數//參數是上傳的文件,若返回false,或返回Primary且被reject,則停止上傳beforeUpload(file) {const isJPG = file.type === 'image/jpeg';const isGIF = file.type === 'image/gif';const isPNG = file.type === 'image/png';const isBMP = file.type === 'image/bmp';const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG && !isGIF && !isPNG && !isBMP) {this.$message.error('上傳圖片必須是JPG/GIF/PNG/BMP 格式!');}if (!isLt2M) {this.$message.error('上傳圖片大小不能超過 2MB!');}return (isJPG || isBMP || isGIF || isPNG) && isLt2M;}, } });解釋
如上的JS代碼,主要是定義一些鉤子函數,這里我么里梳理一下邏輯:
1、點擊ElementUI的上傳組件,瀏覽器自動彈出文件上傳選擇窗口,我們選擇要上傳的圖片。
2、選擇好了要上傳的圖片,點擊彈窗右下角的確定按鈕觸發JS中定義的鉤子函數。
3、首先觸發的鉤子函數是beforeUpload(file)函數,其中的參數file即代表當前上傳的文件對象,beforeUpload()定義了對上傳文件格式校驗。如果不是允許的格式就彈出錯誤信息,并阻止文件上傳,若我那件格式允許,則繼續執行。
4、通過了beforeUpload()函數的校驗,文件開始調用后端接口將數據發送給后端。文件的字段名:picture,格式:multipart/form-data,雖然我們的表單沒有定義enctype="multipart/form-data"屬性,但是HTTP請求頭會自動設置為multipart/form-data類型。
5、這時,如果后端邏輯沒有錯誤,已經正常的將圖片上傳到服務器上了,可以在指定文件夾中查看到已上傳的圖片,那么此時JS中會自動調用handleSuccess()鉤子函數,因為我們設置后端上傳接口上傳成功返回的數據是文件的保存路徑:
那我們就將這個路徑通過Vue的雙向綁定,賦值給表單對象的字段picture,那么提交表單的時候,該字段對應的值就是這個路徑了。
6、如果我們再點擊上傳文件按鈕,就會觸發onExceed()函數,因為我們設置的limit最多上傳一個。
7、如果點擊圖片中的刪除按鈕,就會觸發handleRemove()函數,并刪除此圖片。
8、如果點擊了已上傳的文件列表,就會觸發handlePreview()函數。
實現表單提交
表單提交就比較簡單了,就是觸發對應的click事件,觸發其中定義的函數,將已在data(){}中定義的表單數據發送給后端接口:
提交數據:
后端接口
@RequestMapping("/save") public Result save(Instrument instrument) {if(instrument != null){try{instrumentService.save(instrument);return new Result(true,"添加成功");}catch (Exception e){e.printStackTrace();}}return new Result(false, "發生未知錯誤"); }數據庫中保存的數據:
實現table回顯圖片
table回顯圖片也是很簡單的,僅需要在列中增加一列:
<el-table :data="instrument"><el-table-column label="圖片" width="130"><template scope="scope"><img :src="scope.row.picture" class="picture"/></template></el-table-column><el-table-columnlabel="運行狀態"width="80"prop="operatingStatus"></el-table-column> </el-table>因為使用Vue,根據其雙向綁定的思想,再結合Element-UI提供渲染表格的方式是在<el-table>的:data中指定對應要渲染的數據即可。
注意 ElementUI渲染table的方式是:1、<el-table>中定義:data;2、<el-table-column>中定義prop="data中的參數"。但是因為我們要顯示的是圖片而不是文本數據,所以要在<img>中定義:src="data中的變量"即可實現渲染。
后端就是正常的查詢數據庫數據即可了,為什么數據庫中保存了這個URL圖片就能直接顯示到HTML中,請看我這篇博文: SpringMVC實現文件上傳和下載
作者:TyCoding 鏈接:https://www.jianshu.com/p/decd9e45f1bf總結
以上是生活随笔為你收集整理的Vue+ElementUI+SpringMVC实现图片上传和回显的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IntelliJ IDEA 使用教程(2
- 下一篇: 遇到问题:push的时候出现fatal: