vue + element-ui + springboot + 阿里云OSS 使用表单进行图片文件等的上传(具有上传滚动条效果)

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前端

  • 添加数据时,携带一个文件 + 表单基础数据,一起传递给后台:
  • 页面:
    vue + element-ui + springboot + 阿里云OSS 使用表单进行图片文件等的上传(具有上传滚动条效果)_第1张图片

html页面

  • 页面代码:

          
              
                  
                      
                  
                  
                      
                  
                  
                      
                      
                          选择文件
                          
    只能上传jpg/png文件,且不超过2MB

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依赖

			
			
				com.aliyun.oss
				aliyun-sdk-oss
				3.5.0
			

			
			
				commons-fileupload
				commons-fileupload
				1.3.1
			

controller方法

  • 使用普通的 formData表单提交,必须要 post请求

      @PostMapping("/add")
      public ResponseEntity 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).
                          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){
              // 表示删除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中设置一个 循环定时器,频繁的访问后台,获取后台的上传进度,返回给前台,在将进度值赋值进 进度条组件中。

      
      
      
      
      
    

后端springboot代码

  • 在图片上传时。上传的进度会一直在后台,执行。并且返回有进度条。我们将进度条值,存储起来。

  • 然后在图片上传中时,我们可以进行其他的访问操作,在访问 设置定时器循环 频繁的访问后台,获取进度值。

  • 以下调用的方法,都是工具类 uploadUtils中的方法。

      @RequestMapping("/upload")
      @RestController
      public class UploadController {
      
          @PostMapping
          public ResponseEntity upload(HttpServletRequest request , MultipartFile file) throws IOException {
              UploadUtils.upload(request , file , "");
              return ResponseEntity.ok("上传成功");
          }
      
          @GetMapping("/jd")
          public ResponseEntity getJD(HttpServletRequest request) throws InterruptedException {
              //获取进度
              Integer percent = UploadUtils.getPercent(request);
              System.out.println("我被访问了,进度"+percent);
              return ResponseEntity.ok(percent);
          }
      
          @DeleteMapping("/delete")
          public ResponseEntity delete(){
              UploadUtils.delete("强.jpg" , null);
              return ResponseEntity.ok("删除成功");
          }
      }
    

传成功");
}

	    @GetMapping("/jd")
	    public ResponseEntity getJD(HttpServletRequest request) throws InterruptedException {
	        //获取进度
	        Integer percent = UploadUtils.getPercent(request);
	        System.out.println("我被访问了,进度"+percent);
	        return ResponseEntity.ok(percent);
	    }
	
	    @DeleteMapping("/delete")
	    public ResponseEntity delete(){
	        UploadUtils.delete("强.jpg" , null);
	        return ResponseEntity.ok("删除成功");
	    }
	}

你可能感兴趣的:(springboot,vue,vue,elementUI图片上传,图片上传滚动条,表单中上传图片,el-upload)