vue + element-ui + springboot + 阿里云OSS 使用表单进行图片文件等的上传(具有上传滚动条效果)
2020-01-14 15:35
1056 查看
vue + element-ui + springboot + 阿里云OSS 使用表单进行图片文件等的上传(具有上传滚动条效果)
-
使用vue + elementUI的前端页面中,使用el-upload组件,在添加,或者修改时。在表单中,加入图片。一起传给后台 springboot服务器,将文件上传给 阿里云OSS。
-
具有上传效果 滚动条效果
-
小编的代码项目地址:https://github.com/kedaya-github/vue_system
所需工具
-
开通阿里云 OSS对象存储。创建Bucket
-
前端vue + elementUI项目 —Visual Studio Code
-
后端 springboot项目 — idea
-
以下代码复制,修改配置和属性后可直接使用,话不多说,老表,上手吧。
vue前端
- 添加数据时,携带一个文件 + 表单基础数据,一起传递给后台:
- 页面:
html页面
-
页面代码:
<el-dialog title="添加品牌" :visible.sync="dialogFormVisible"> <el-form :model="addBrand" ref="addBrand"> <el-form-item label="品牌名称"> <el-input v-model="addBrand.name" autocomplete="off"></el-input> </el-form-item> <el-form-item label="品牌首字母"> <el-input v-model="addBrand.letter" autocomplete="off"></el-input> </el-form-item> <el-form-item label="添加图片" ref="uploadElement" prop="img"> <!-- 添加图片上传: 设置:auto-upload="false" ; 关闭组件的默认自动上传 action : 随便设置 :on-change="handleChange" : 当组件的图片修改时,调用函数方法,来判断图片的格式大小,并替换图片 :file-list="fileList" : 展示图片列表 --> <el-upload class="upload-demo" action="#" accept="image/jpeg,image/jpg,image/png" ref="upload" :auto-upload="false" :on-change="handleChange" :file-list="fileList"> <el-button size="small" type="primary">选择文件</el-button> <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2MB</div> </el-upload> </el-form-item> <el-form-item> <el-select v-model="checkList" multiple placeholder="请选择"> <el-option v-for="(category,index) in categorys" :key="index" :label="category.name" :value="category.id"> </el-option> </el-select> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false">取 消</el-button> <el-button type="primary" @click="upload()">确 定</el-button> </div> </el-dialog>
js代码,函数方法
-
js代码:
-
与html代码,配合一起使用。
-
具有判断图片的格式 和 大小的方法。
-
一次只能上传一个文件
//图片方法 //图片进行修改的方法 handleChange(file, fileList) { let bo = this.beforeAvatarUpload(file); if(!bo){ //图片不符合规范 this.fileList = []; //图片列表赋值为空 return; } //如果图片符合 规范,将之前的图片剪切,覆盖掉 this.fileList = fileList.slice(-1); }, //图片判断,大小 beforeAvatarUpload(file) { const isJPG = file.raw.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; }, //添加方法 async upload(){ //将下拉框 选择的分类id,拼接成字符串,赋值给 addBrand对象中 this.addBrand.categoryIds = this.checkList.toString(); //上传图片 + 表单数据一起传给后台 let fd = new FormData(); //判断是否有文件 if(this.fileList.length != 0){ fd.append("file" , this.fileList[0].raw); } //添加格外的表单基本数据 fd.append("name" , this.addBrand.name); fd.append("letter" , this.addBrand.letter); fd.append("categoryIds" , this.addBrand.categoryIds); //必须使用 post请求,因为是原生的 数据提交 let {data} = await this.$ajax.post("/brand/add" , fd); this.findAll(); this.dialogFormVisible = false; },
上传图片的原理解析
- :on-change=“handleChange” : 在组件的图片改变时,会调用此函数方法,来判断图片的格式是否正确。
- :file-list=“fileList” : 存储的文件列表,当前只上传一个文件,修改图片时,使用fileList.slice(-1);剪切掉之前的,只保留一个,存储在fileList属性中
- 使用 new FormData(); 来存储各项数据 和 文件图片。发送post请求,访问后台
springboot后端代码
- idea项目
添加上传文件所需要的 pom依赖
<!-- TODO 上传文件到阿里云 oss对象存储空间 --> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.5.0</version> </dependency> <!-- TODO MultipartFile转File类型 DiskFileItem需要引入依赖--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
controller方法
-
使用普通的 formData表单提交,必须要 post请求
@PostMapping("/add") public ResponseEntity<BaseResult> add(MultipartFile file , HttpServletRequest request , Brand brand) throws IOException { brandService.add(brand); BaseResult br = brandService.upload(request,file,brand); //将返回的 br中data 的url地址,赋值给 brand对象地址的 image中 brand.setImage(String.valueOf(br.getData())); //将当前brand对象的 image属性修改 //修改数据库中的 image字段 brandService.updateImage(brand); //br为 图片上传的结果, data为上传上图片的url路径 return ResponseEntity.ok(br); }
service方法
-
在service方法中,调用 uploadUtils工具类,进行提交
-
当前的提交效果为: 每个数据用户都拥有自己的一个 目录文件夹,来存储文件。 文件夹名称为 brand的id
public BaseResult upload(HttpServletRequest request , MultipartFile file , Brand brand) throws IOException { //上传图片 String url = ""; //判断file是否为null,前端是否传过来了 图片 if (file == null){ return new BaseResult(CommonUtils.SUCCESS , "失败" , url); } try { //三个参数: file:文件 , request : 请求 , tableName : 目录名称,没有目录可以为"" or null UploadUtils.upload(request , file , "brand_"+brand.getId()); url = UploadUtils.getURL(file.getOriginalFilename() , "brand_"+brand.getId()); return new BaseResult(CommonUtils.SUCCESS , "成功" , url); } catch (Exception e) { e.printStackTrace(); return new BaseResult(CommonUtils.SUCCESS , "失败" , url); } }
uploadUtils上传文件的工具类
-
此工具类,可以实现,上传文件进度的滚动条获取
-
该工具类 具有 上传,获取文件url地址,删除。等功能
-
会自动将 MultipartFile 类型 转为 File类型
-
可以添加 添加上传文件的目录
/** * @author 遗憾就遗憾吧 * @Date 2019/11/15 * @jdk 1.8 * 阿里云oss上传文件 工具类 */ public class UploadUtils { // Endpoint以杭州为例,其它Region请按实际情况填写。 //endpoint 的 地址需要与你的 Bucket地址对应。 如果Bucket为shanghai,就设置为shanghai private static String endpoint = "http://oss-cn-shanghai.aliyuncs.com"; //云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建。 private static String accessKeyId = ""; private static String accessKeySecret = ""; private static String bucketName = "2019-11-15"; //滚动条值 private static Integer percent = 0; /** * 用于外界赋值,目录名称。 * 需求:每个品牌都拥有自己独立的一个 目录来存储文件 */ public static void upload(HttpServletRequest request , MultipartFile file , String tableName) throws IOException { System.out.println(file.getOriginalFilename()); //TODO 进行赋值 文件的上传名称 包含目录 , 在赋值 tableName 中最后加上 / 隔开 String objectName = ""; if (tableName != null && !tableName.isEmpty()){ objectName = tableName+"/"+file.getOriginalFilename(); }else{ objectName = file.getOriginalFilename(); } //每次进入方法,就滚动条设置0 setPercent(request); //将 MultipartFile 转为 File类型,进行上传到 oss File toFile = null; if (file.equals("") || file.getSize() <= 0) { file = null; } else { InputStream ins = null; ins = file.getInputStream(); toFile = new File(file.getOriginalFilename()); inputStreamToFile(ins, toFile); ins.close(); } // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try { // 带进度条的上传。 PutObjectResult putObjectResult = ossClient.putObject(new PutObjectRequest(bucketName, objectName, toFile). <PutObjectRequest>withProgressListener(new PutObjectProgressListener(request))); } catch (Exception e) { e.printStackTrace(); } // 关闭OSSClient。 ossClient.shutdown(); //最后删除掉,刚创建的 本地临时文件 deleteTempFile(toFile); } /** * @param objectName 文件的名称 * @param tableName 目录的名称 * @return 获取上传文件的的 地址值 */ public static String getURL(String objectName , String tableName){ // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); //通过 ossClient 可以获取 刚上传文件的 访问URL Date expiration = new Date(new Date().getTime() + 5 * 60 * 10000); //判断目录是否 为空 或者 null if (tableName != null && !tableName.isEmpty()){ objectName = tableName+"/"+objectName; } URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration); System.out.println(url.toString()); // 关闭OSSClient。 ossClient.shutdown(); return url.toString().split("\\?")[0]; } /** * @param objectName 删除阿里云OSS上 存储的对应 fileName的文件 * @param tableName 删除阿里云OSS上 存储的对应 fileName的目录 */ public static void delete(String objectName , String tableName){ // <yourObjectName>表示删除OSS文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 //判断目录是否 为空 或者 null if (tableName != null && !tableName.isEmpty()){ objectName = tableName+"/"+objectName; } // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 删除文件。 ossClient.deleteObject(bucketName, objectName); // 关闭OSSClient。 ossClient.shutdown(); } /** * @param request 获取当前滚动条的数值 * @return */ public static Integer getPercent(HttpServletRequest request){ return UploadUtils.percent; } /** * @param request 将滚动条 重置0 */ private static void setPercent(HttpServletRequest request){ //每次进入,upload上传图片方法,就赋值 upload_percent 为0 ; 重置长度 //防止 GET请求获取 进度条值 upload_percent时,出现异步,先获取的问题 //request.getSession().setAttribute("upload_percent" , 0); UploadUtils.percent = 0; } /** * 获取流文件,将流文件 赋值给 file * @param ins * @param file */ private static void inputStreamToFile(InputStream ins, File file) { try { OutputStream os = new FileOutputStream(file); int bytesRead = 0; byte[] buffer = new byte[8192]; while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); ins.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 删除本地临时文件 * @param file */ private static void deleteTempFile(File file) { if (file != null) { File del = new File(file.toURI()); del.delete(); } } /** * 上传图片的 滚动条进行 存储到 session中。 * 当前存储在成员变量中。可能会产生某些问题 */ private static class PutObjectProgressListener implements ProgressListener { private long bytesWritten = 0; private long totalBytes = -1; private boolean succeed = false; private HttpServletRequest request; public PutObjectProgressListener(HttpServletRequest request) { this.request = request; } @Override public void progressChanged(ProgressEvent progressEvent) { long bytes = progressEvent.getBytes(); ProgressEventType eventType = progressEvent.getEventType(); switch (eventType) { case TRANSFER_STARTED_EVENT: System.out.println("Start to upload......"); break; case REQUEST_CONTENT_LENGTH_EVENT: this.totalBytes = bytes; System.out.println(this.totalBytes + " bytes in total will be uploaded to OSS"); break; case REQUEST_BYTE_TRANSFER_EVENT: this.bytesWritten += bytes; if (this.totalBytes != -1) { int percent = (int) (this.bytesWritten * 100.0 / this.totalBytes); System.out.println("我在赋值中"+percent); // request.getSession().setAttribute("upload_percent",percent); UploadUtils.percent = percent; System.out.println(bytes + " bytes have been written at this time, upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")"); } else { System.out.println(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)"); } break; case TRANSFER_COMPLETED_EVENT: this.succeed = true; System.out.println("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total"); break; case TRANSFER_FAILED_EVENT: System.out.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred"); break; default: break; } } public boolean isSucceed() { return succeed; } } }
上传文件的带有滚动条效果
前端HTML代码:
-
通过在js中设置一个 循环定时器,频繁的访问后台,获取后台的上传进度,返回给前台,在将进度值赋值进 进度条组件中。
<template> <div> <el-upload class="upload-demo" action="http://localhost:8090/upload" :on-progress="getProgress" :file-list="fileList" list-type="picture" name="file" :with-credentials="true" style="width:30%"> <el-button size="small" type="primary">点击上传</el-button> </el-upload> <el-progress v-if="isTure" :text-inside="true" :stroke-width="26" :percentage="percentage" :color="customColors" style="width: 30%;"></el-progress> </div> </template> <script> export default { data() { return { fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}], customColors: [ {color: '#f56c6c', percentage: 20}, {color: '#e6a23c', percentage: 40}, {color: 'rgb(33, 187, 207)', percentage: 60}, {color: '#1989fa', percentage: 80}, {color: 'rgb(81, 184, 81)', percentage: 100} ], //颜色展示 isTure : false , //是否展示 滚动条 percentage : 0 , //滚动条数据 } }, methods:{ getProgress(event, file, fileList){ //将进度条打开 this.isTure = true; //此方法的开始,将percentage赋值0 this.percentage = 0; //访问后台,获取滚动条数据 //每隔 0.1秒访问一次后台,获取一次进度条数据 let time = setInterval( () =>{ //调用 获取进度条的方法 this.getJD(); if(this.percentage >= 100){ clearInterval(time); this.isTure = false; this.percentage = 0; return; } } , 100); }, async getJD(){ let {data} = await this.$ajax.get("/upload/jd"); console.log(data); this.percentage = data; } }, } </script> <style> </style>
后端springboot代码
-
在图片上传时。上传的进度会一直在后台,执行。并且返回有进度条。我们将进度条值,存储起来。
-
然后在图片上传中时,我们可以进行其他的访问操作,在访问 设置定时器循环 频繁的访问后台,获取进度值。
-
以下调用的方法,都是工具类 uploadUtils中的方法。
@RequestMapping("/upload") @RestController public class UploadController { @PostMapping public ResponseEntity<String> upload(HttpServletRequest request , MultipartFile file) throws IOException { UploadUtils.upload(request , file , ""); return ResponseEntity.ok("上传成功"); } @GetMapping("/jd") public ResponseEntity<Integer> getJD(HttpServletRequest request) throws InterruptedException { //获取进度 Integer percent = UploadUtils.getPercent(request); System.out.println("我被访问了,进度"+percent); return ResponseEntity.ok(percent); } @DeleteMapping("/delete") public ResponseEntity<String> delete(){ UploadUtils.delete("强.jpg" , null); return ResponseEntity.ok("删除成功"); } }
传成功");
}
@GetMapping("/jd") public ResponseEntity<Integer> getJD(HttpServletRequest request) throws InterruptedException { //获取进度 Integer percent = UploadUtils.getPercent(request); System.out.println("我被访问了,进度"+percent); return ResponseEntity.ok(percent); } @DeleteMapping("/delete") public ResponseEntity<String> delete(){ UploadUtils.delete("强.jpg" , null); return ResponseEntity.ok("删除成功"); } }
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- SpringBoot+element-ui进行文件上传
- vue+elementUI实现表单和图片上传及验证功能示例
- vue+elementUi图片上传组件使用详解
- SpringBoot集成阿里云OSS图片上传
- vue2.0 使用element-ui里的upload组件实现图片预览效果方法
- [云计算] 在 SpringBoot 中使用 阿里云OSS云储存保存、显示图片
- Spring Boot上传图片或文件并且进行访问(至指定盘符)
- 使用grunt上传文件到阿里云(对ali-oss进行grunt封装)
- vue中使用element-ui进行表单验证
- vue中使用element-ui进行表单验证的实例代码
- spring boot 图片上传阿里云oss云存储
- vue2.0 使用element-ui里的upload组件实现图片预览效果
- springBoot通过表单的提交进行AmazonS3 进行文件的上传下载删除(不存储在本地)。
- 使用springboot进行文件上传和下载
- SpringBoot+Mybatis+MySQL+Vue+ElementUI,用POI导出和导入Excel文件案例
- Vue使用阿里云OSS上传文件步骤
- Spring Boot + Vue Element实现Excel文件上传、解析、下载(含完整实现过程)
- Springboot+mybatis集成上传文件至阿里云OSS中,(不经过服务器,直接上传到OSS)
- springboot上传文件到阿里云OSS
- Springboot 上传文件至阿里云OSS