1. 前言
本篇文章的标题,应该是我写过的,关于Element组件介绍的文章里面,最长的一个了。
无它,就是因为这个组件确实使用起来比较复杂,而且必须搭配上后端的讲解,才能到位。
另外,我感觉对于el-upload上传组件的介绍,官方文档写的有点乱,不知道是的确有点乱,还是官方水平太高我看不懂。
好了,本篇按我的思路来介绍下el-upload的用法。
2. 基本用法
2.1 前端部分
el-upload上传组件的基本用法是非常简单的,代码如下:
基本用法:<br><br>
<el-upload :action="actionUrl">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
actionUrl: 'http://127.0.0.1:8080/upload',
1
只需要解释两点,一是actionUrl表示文件上传对应的后台服务地址,二是el-upload标签中间可以放置任何内容,点击中间的内容会触发弹窗选择文件,选中文件后会自动上传到指定actionUrl。
上述代码效果如下,实现起来非常简单。
2.2 后端部分
后端部分实现起来也很简单,接受一个文件然后存储即可,为了防止文件重名,此处我还添加了重命名机制,使用UUID代替原来的文件名进行存储。
@RequestMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
String filePath = "D:\\images\\";
String fileName = file.getOriginalFilename();
String fileType = fileName.substring(fileName.lastIndexOf("."), fileName.length());
String fileNewName = UUID.randomUUID() + fileType;
File targetFile = new File(filePath);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
FileOutputStream out = null;
try {
out = new FileOutputStream(filePath + fileNewName);
out.write(file.getBytes());
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
return "";
}
return fileNewName;
}
需要注意的是,后端返回值是存储的真实文件名,最后我们在提交的时候,可以将业务信息与真实文件名一起提交存入数据库,这样就能把业务信息和文件对应起来了。
上传成功后界面显示如下,注意界面上显示的是上传文件的原名,不是后端返回的存储文件名。
2.3 获取后端返回信息
有时候我们需要获取后端返回的文件存储名,以便将该文件信息存入数据库。此时我们可以通过on-sucess绑定一个方法,该方法在上传成功时调用,其参数中就有后端返回信息。
基本用法:<br><br>
<el-upload :action="actionUrl" :on-success="handleSuccess">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
handleSuccess(response, file, fileList) {
console.log(response, file, fileList);
},
上传成功后,response即为后端返回值,另外file及fileList对象中也有后端返回值信息,感兴趣的可以从控制台详细查看了解。
注意后端需要跨域,如果是Spring Boot项目的话,跨域代码参考如下:
/**
* CORS跨域配置类
*/
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
3. 外观功能介绍
接下来,介绍与外观相关的功能,el-upload可以通过修改参数,实现更好看的外观效果。
3.1 拖拽上传
通过设置drag属性即可启动拖拽上传,极其简单,当然控件中间的内容可以自定义,只要好看就行。
拖拽上传:<br><br>
<el-upload :action="actionUrl" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
效果如下:
3.2 显示图片
可以显示上传的图片,在el-upload中添加img,然后上传成功后设置图片内容即可。
显示图片:<br><br>
<el-upload :action="actionUrl" :limit="2" :on-success="handleSuccessWithImage">
<el-button size="small" type="primary">点击上传</el-button>
<img v-if="imageUrl" :src="imageUrl" class="my-image">
</el-upload>
actionUrl: 'http://127.0.0.1:8080/upload',
imageUrl: '',
handleSuccessWithImage(response, file, fileList) {
this.imageUrl = URL.createObjectURL(file.raw);
},
效果如下:
3.3 设置文件列表样式
如果觉得上面显示图片的方式不好看,没关系,el-upload提供了显示文件列表的方式,美观大方,而且使用很简单。通过list-type属性设置即可。(el-divider用于区分不同的演示内容,只是为了方便观看,跟本章内容没关系。)
设置文件列表样式(text):<br><br>
<el-upload :action="actionUrl" list-type="text">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<el-divider></el-divider>
设置文件列表样式(picture):<br><br>
<el-upload :action="actionUrl" list-type="picture">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<el-divider></el-divider>
设置文件列表样式(picture-card):<br><br>
<el-upload :action="actionUrl" list-type="picture-card">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<el-divider></el-divider>
效果如下,可见后两种效果还是很好看的。
3.4 显示提示信息
还可以在内部显示一些详细提示信息:
显示提示信息:<br><br>
<el-upload :action="actionUrl">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">上传文件大小不能超过500kb</div>
</el-upload>
<el-divider></el-divider>
效果如下:
4. 事件功能介绍
上面介绍了el-upload的外观部分,如果要实现一些复杂功能,还需要借助事件来实现。
4.1 限制上传文件数量
可以通过limit属性设置文件上传的最大数量,同时通过on-exceed指定文件超出数量限制时的钩子方法。
限制上传数量:<br><br>
<el-upload :action="actionUrl" :limit="2" :on-exceed="handleExceed">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">上传文件大小不能超过500kb,最多只能上传2个文件</div>
</el-upload>
handleExceed(files, fileList) {
console.log(files, fileList);
this.$message.warning("最多只能同时上传2个文件");
},
4.2 限制上传文件类型和大小
可以通过beforeUpload指定上传文件钱的钩子方法,该方法返回true则可以上传,返回false则终止上传。所以可以在该方法中限制上传文件的类型和大小,代码如下:
限制上传类型和大小:<br><br>
<el-upload :action="actionUrl" :before-upload="beforeUpload">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
beforeUpload(file) {
let sizeByMb = file.size / 1024 / 1024;
if (sizeByMb > 2) {
this.$message.warning("上传文件不能超过2M");
return false;
}
if (file.type != 'image/jpeg') {
this.$message.warning("只能上传图片");
return false;
}
return true;
},
当上传文件大于2M或者不是图片时,会弹出消息提示,并取消文件上传动作。
4.3 移除文件处理
当我们点击文件列表的删除按钮,移除文件时,有时候我们会希望将该消息事件传递到后端,并告知后端要移除文件的信息,此时可以接住on-remove实现。
移除文件处理:<br><br>
<el-upload multiple :action="actionUrl" :on-remove="handleRemove">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
handleRemove(file, fileList) {
console.log(file, fileList);
},
file中包含移除文件的信息,此时可以发起ajax请求到后端处理响应逻辑。
4.4 手动上传
个别情况下,也会不希望选中文件后立即上传,而是先选择文件,再手工上传。通过auto-upload属性来实现:
手动上传:<br><br>
<el-upload ref="myUpload" multiple :action="actionUrl" :auto-upload="false">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" size="small" type="success" @click="btnUpload">上传到服务器</el-button>
</el-upload>
btnUpload() {
this.$refs.myUpload.submit();
},
5. 附带参数
在上传文件时,例如上传Excel表格。有时候我们希望同时附带一些参数,例如Excel表格关联的部门编号等。此时可以通过data属性来指定。
附带参数:<br><br>
<el-upload :action="actionUrl2" :data="uploadData">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
actionUrl2: 'http://127.0.0.1:8080/uploadWithParam',
uploadData: {
userId: '001'
},
后端同时接收文件和参数:
@RequestMapping("/uploadWithParam")
public String uploadWithParam(@RequestParam("file") MultipartFile file, @RequestParam("userId") String userId) {
System.out.println("userId:" + userId);
String filePath = "D:\\images\\";
String fileName = file.getOriginalFilename();
String fileType = fileName.substring(fileName.lastIndexOf("."), fileName.length());
String fileNewName = UUID.randomUUID() + fileType;
File targetFile = new File(filePath);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
FileOutputStream out = null;
try {
out = new FileOutputStream(filePath + fileNewName);
out.write(file.getBytes());
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
return "";
}
return fileNewName;
}
注意,可以再before-upload指定的钩子方法中修改上传的参数值。
6. 附带请求头部
在前后端分离的项目中,我们经常把验证信息放入headers头部,然后由前端传递到后端,此时可以接住headers属性实现。
附带请求头部:<br><br>
<el-upload :action="actionUrl2" :data="uploadData" :headers="uploadHeaders">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
actionUrl2: 'http://127.0.0.1:8080/uploadWithParam',
uploadData: {
userId: '001'
},
uploadHeaders: {
token: '123456'
}
后端SpringBoot程序可以通过拦截器接收,配置拦截器代码如下:
/**
* Web配置类
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
/**
* 添加Web项目的拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 对所有访问路径,都通过MyInterceptor类型的拦截器进行拦截
registry.addInterceptor(myInterceptor).addPathPatterns("/**");
}
}
拦截器代码如下:
/**
* 自定义拦截器类
*/
@Component
public class MyInterceptor implements HandlerInterceptor {// 实现HandlerInterceptor接口
/**
* 访问控制器方法前执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
System.out.println("token:" + token);
return true;
}
}
7. 小结
el-upload上传组件功能比较全面,使用起来也比较复杂,本篇给出了相对完整的介绍,大家可以参考实现。