前言:
我們在設計自己的網站的時候,一定會遇到上傳圖片的功能,比如:用戶頭像,商品圖片。
這篇文章將帶著大家設計一個可以使用的圖片上傳功能,請大家一步一步來,讓我們在碼路上越走越遠。
前端:
組件引入
前端我們使用element-ui的組件。我這里以html加js的方式
1:引入vue.js,axIOS.js,element-ui。
<script src="../static/js/util/vue.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<!-- 引入樣式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入組件庫 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
基礎文件上傳
2:element-ui中有多個例子,我們使用其中一個:
<el-upload
class="avatar-uploader"
action="/Manage/upBusinessImage"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
<script>
export default {
data() {
return {
imageUrl: ''
};
},
methods: {
handleAvatarSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw);
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上傳頭像圖片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上傳頭像圖片大小不能超過 2MB!');
}
return isJPG && isLt2M;
}
}
}
</script>
上面是element-ui中的一個例子。我將會對其中的各個參數進行講解。
其中的樣式,我們不進行講解,直接復制就可以。
el-upload中的參數:
action:后面是接口url,圖片文件將會發送到該接口中。
:show-file-list:是否顯示上傳的圖片列表
:on-success:上傳成功后要執行的操作,“:”代表與js代碼進行了綁定。
:before-upload:上傳之前要執行的操作,比如檢驗是否是圖片文件,圖片的大小是否符合要求等。
在它的一個函數中使用了URL.createObjectURL(file.raw);方法,這個地方要注意:elementUI中,自帶的方法中的file,并不是指圖片本身,而是他的一個dom。如果要是拿他的圖片,就要用file.raw。
自定義上傳方法
通過上面的方式就可以將圖片文件發送給后端,但是,這個只是基礎的功能,往往我們的業務不會如此簡單,比如:我們可能將商品id,等信息一同發送后端,以保證后端確定圖片的作用。此時上面的方式就滿足不了我們的需求了。
為此我們需要設計自己的上傳方法。于是改造過程:
1:action后面的路徑改為空:action=""
2:添加屬性:http-request,后面跟自定義的方法名,例如::http-request=“uploader”
3:在js中書寫自定義方法“uploader”
async uploader(params){
let file = params.file;
let clothesId;
let styleId;
let imgUrl;
clothesId = this.goodsModify.goodsId;
styleId = this.goodsModify.styleId;
imgUrl = this.goodsModify.goodsImg
formData = new FormData();
formData.Append('file', file);
formData.append('clothesId',clothesId);
formData.append('styleId',styleId);
formData.append('imgUrl',imgUrl);
let data = await axios.post("/Manage/upBusinessImage",formData)
},
說明一下如果要傳遞的是多個參數,則必須把多個參數整理成formData的形式進行發送。而到后端則需要用@RequestParam注解標識進行接收。
后端:
需要引入的jar包:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
基礎文件上傳
Controller層:
@RequestMapping(value = "/Manage/upBusinessImage",method = RequestMethod.POST)
public CommonResultVo uploadBusinessImage(@RequestParam(value = "file", required = false) MultipartFile file) {
return fileService.uploadImage(file,"D:/img/HeadImages/");
}
因為只傳遞了文件,所以只需要一個MultipartFile類型的file接收就可以了。
server層:
//上傳操作
private CommonResultVo uploadImage(MultipartFile file,String folder){
if (file == null) {
return CommonResultVoUtil.error("請選擇要上傳的圖片");
}
if (file.getSize() > 1024 * 1024 * 10) {
return CommonResultVoUtil.error("文件大小不能大于10M");
}
//獲取文件后綴
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1, file.getOriginalFilename().length());
if (!"jpg,jpeg,gif,png".toUpperCase().contains(suffix.toUpperCase())) {
return CommonResultVoUtil.error("請選擇jpg,jpeg,gif,png格式的圖片");
}
String savePath = folder;
File savePathFile = new File(savePath);
if (!savePathFile.exists()) {
//若不存在該目錄,則創建目錄
savePathFile.mkdir();
}
//通過UUID生成唯一文件名
String filename = UUID.randomUUID().toString().replaceAll("-","") + "." + suffix;
try {
//將文件保存指定目錄
//file.transferTo(new File(savePath + filename));
//File file1 = new File(file.getOriginalFilename());
FileUtils.copyInputStreamToFile(file.getInputStream(),new File(savePath + filename));
} catch (Exception e) {
e.printStackTrace();
return CommonResultVoUtil.error("保存文件異常");
}
//返回文件名稱
return CommonResultVoUtil.successWithData(filename,1);
}
代碼里的CommonResultVoUtil是我自定義的結果工具類,大家可以根據自己的需求自己構建,也可直接返回字符串成功或者失敗。
自定義的多參數接口
與上面的區別只是多使用了幾個參數:
@RequestMapping(value = "/Manage/upBusinessImage",method = RequestMethod.POST)
public CommonResultVo uploadBusinessImage(@RequestParam(value = "file", required = false) MultipartFile file,
@RequestParam(value = "clothesId", required = false) String clothesId,
@RequestParam(value = "styleId", required = false) String styleId,
@RequestParam(value = "imgUrl", required = false) String imgUrl) {
return fileService.uploadBusinessImage(file,clothesId,styleId,imgUrl);
}
拿到這些參數后可以根據某些參數去定位數據庫中的某條記錄,然后將圖片位置保存入數據庫中,以便后續訪問。