spring boot + vue新增上傳圖片功能
餘近日開發spring boot +vue的後臺管理專案,涉及到檔案上傳功能,使用之前專案的檔案上傳模組,一直有問題。遂經過兩天的百度,加個人理解,最終解決了基本的檔案上傳功能。
首先,html頁面:
<!--form中是要加這個enctype的--> <form class="form-horizontal" enctype="multipart/form-data"> <div v-if="menu.type == 1" class="form-group"> <div class="col-sm-2 control-label">圖片</div> <div class="col-sm-10"> <div class="ui-upfile"> <div style="width: 150px;height: 140px;display:none;" class="file-area" /> </div> <input type="hidden" name="menuImgUrl" class="menu-image-url" v-model="menu.menuImgUrl"> <input type='button' class='btn' value='上傳圖片'onclick="document.getElementById('file').click()" style="background-color: #48aae3c7;"/> <input type="file" class="menu-image-url" value="" id="file" @change="onUpload" style="filter:alpha(opacity:0);opacity:0;width:0px"> </div> </div> </div>
這裡要說明一下,由於使用的是vue,所有這裡賦值取值都是使用v-model,然後這裡為什麼會有這麼多input框,
第一個是返回我物件的屬性值的;
第二個是手寫的一個按鈕,因為如果直接使用input type=file的話,樣式比較醜,還會有未選擇檔案那個字樣 ,可以那個type=file的input又是必須的。
所以這裡我們使用一個button去覆蓋type=file的功能,並且把type=file的input隱藏起來,這裡的核心程式碼是:opacity:0;
接下來,js程式碼:
onUpload(e){ var files = e.target.files[0]; var formFile = new FormData(); formFile.append("file", files); $.ajax({ url: baseURL + 'sys/upload/uploadPic',//這裡是請求後臺的上傳檔案介面 type: 'POST', dataType: 'json', cache: false, data: formFile, processData: false, contentType: false, success: function(r){ if (r.code === 0) { vm.menu.menuImgUrl = r.fileUrl; $(".file-area").css("display","block"); $(".file-area").html("<img src= '"+ r.fileUrl +"'>"); }else{ alert("檔案上傳失敗:" + r.msg); } } }); }
由於使用的是vue,所以這裡是寫在methods下面的。
這裡主要是請求後臺,把檔案傳過去,然後返回一個url,通過這個url我們可以直接訪問到圖片。
後臺 UploadController類
@RestController @RequestMapping("/sys/upload") public class UploadController extends BaseController { /** * 上傳圖片 * @param file * @param request * @throws IOException */ @RequestMapping( value = "/uploadPic") @ResponseBody public R uploadPic(@RequestParam(value = "file", required = false) MultipartFile file, HttpServletRequest request) throws IOException { //目前這裡是寫死的本地硬碟路徑 String path = "D:/img"; logger.info("path:" + path); //獲取檔名稱 String fileName = file.getOriginalFilename(); //獲取檔名字尾 Calendar currTime = Calendar.getInstance(); String time = String.valueOf(currTime.get(Calendar.YEAR))+String.valueOf((currTime.get(Calendar.MONTH)+1)); //獲取檔名字尾 String suffix = fileName.substring(file.getOriginalFilename().lastIndexOf(".")); suffix = suffix.toLowerCase(); if(suffix.equals(".jpg") || suffix.equals(".jpeg") || suffix.equals(".png")/* || suffix.equals(".gif")*/){ fileName = UUID.randomUUID().toString()+suffix; File targetFile = new File(path, fileName); if(!targetFile.getParentFile().exists()){ //注意,判斷父級路徑是否存在 targetFile.getParentFile().mkdirs(); } long size = 0; //儲存 try { file.transferTo(targetFile); size = file.getSize(); } catch (Exception e) { e.printStackTrace(); return R.error("上傳失敗!"); } //專案url,這裡可以使用常量或者去資料字典獲取相應的url字首; String fileUrl="http://localhost:8080"; //檔案獲取路徑 fileUrl = fileUrl + request.getContextPath() + "/img/" + fileName; logger.info("fileUrl:" + fileUrl); return R.ok().put("fileUrl", fileUrl); }else{ return R.error("圖片格式有誤,請上傳.jpg、.png、.jpeg格式的檔案"); } } }
這裡有個坑,就是由於spring boot使用的內建tomcat,所以會自動在系統盤下生成一個編譯路徑,大概是這樣的:
C:\Users\69223\AppData\Local\Temp\tomcat-docbase.6718506550492189172.8080
可是把檔案放到這個下面,我們無法去正確獲取,而且這裡的tomcat生成的資料夾中間那一段數字,還都是在變化的。具體原因沒有細究。
經過一天的百度及個人理解,最終決定使用對映;
在application.yml檔案中新增要對映的絕對路徑,即圖片要儲存的位置:
#檔案上傳
cbs:
imagesPath:
file:/D:/img/
yml檔案中格式要求極為嚴格 ,必須是4個空格,tab鍵不起作用,直接使用cbs.imagesPath.file也報錯。
這裡的檔案絕對路徑就是我們上傳檔案時寫的上傳路徑;
之後編寫WebMvcConfig配置檔案;
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/login.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers( registry );
}
/**
* 在配置檔案中配置的檔案儲存路徑
*/
@Value("${cbs.imagesPath}")
private String mImagesPath;
@Bean
public MultipartConfigElement multipartConfigElement(){
MultipartConfigFactory factory = new MultipartConfigFactory();
//檔案最大KB,MB
factory.setMaxFileSize("1024MB");
//設定總上傳資料總大小
factory.setMaxRequestSize("1024MB");
return factory.createMultipartConfig();
}
/**
* 這裡是對映檔案路徑的方法
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if(mImagesPath.equals("") || mImagesPath.equals("${cbs.imagesPath}")){
String imagesPath = WebMvcConfig.class.getClassLoader().getResource("").getPath();
if(imagesPath.indexOf(".jar")>0){
imagesPath = imagesPath.substring(0, imagesPath.indexOf(".jar"));
}else if(imagesPath.indexOf("classes")>0){
imagesPath = "file:"+imagesPath.substring(0, imagesPath.indexOf("classes"));
}
imagesPath = imagesPath.substring(0, imagesPath.lastIndexOf("/"))+"/img/";
mImagesPath = imagesPath;
}
registry.addResourceHandler("/img/**").addResourceLocations(mImagesPath);
super.addResourceHandlers(registry);
}
}
addResourceHandlers()方法是對映檔案路徑的方法;
這裡我們還需要在許可權配置類中新增如下,即放開img下的許可權控制,否則會涉及到許可權,被攔截;
filterMap.put("/img/**", "anon");
截止到這裡,我們的上傳圖片基本已經完成了,接下來就可以進入測試階段。
我們把檔案上傳到D盤下面的img資料夾,上傳成功之後,我們使用:
http://localhost:8080/專案名/img/3b13ad02-3812-4c39-880d-799172801284.png
就可以直接訪問到我們的圖片了。
專案得啟動起來。
只是基本的使用,具體的底層原理,並未深究。
點個贊吧!^_^ !