自定义vue组件--实现多图片上传

一 引入

文件上传在日常的开发中是一项基本的操作,在前端中得以广泛的使用,因此将其封装成一个组件显得极为重要,本文主要是基于vue实现的自定义多图片上传组件.

二 自定义vue上传组件

MultiUpload组件的封装

<template>
  <div>
    <el-upload :disabled="uploadEdit" class="uploader" :headers="authorToken" :action="UPLOAD_URL" :auto-upload="true"
               :file-list="fileList" list-type="picture-card" :limit="limit?limit:9" :accept="fileType?fileType:'image/*'"
               :on-success="handleGoodsImagesUploadSuccess" :before-upload="handlebeforeUpload" :multiple="true"
               ref="fileupload" :on-exceed="handleUploadExceed" :on-remove="handleRemove"
               :on-preview="handlePictureCardPreview">
      <i class="el-icon-plus">i>
    el-upload>
    <el-dialog :disabled="uploadEdit" :append-to-body="true" :visible.sync="dialogImgVisible" style="z-index: 3000;text-align: center;"
               :close-on-click-modal="false" :close-on-press-escape="false" custom-class="pub_dialog">
      <img width="80%" :src="dialogImageUrl" alt="" />
    el-dialog>
  div>
template>



<script>
export default {
  props: {
    value: {
      type: Array,
      default: () => []
    },
    limit: {
      type: Number,
      default: 9
    },
    fileType: String,
    uploadEdit: Boolean,
  },
  data() {
    return {
      authorToken: {
        'Authorization': 'Bearer ' + JSON.parse(window.sessionStorage.getItem('cncloud-access_token')).content
      },
      UPLOAD_URL: "/admin/sys-file/upload", // 上传的图片服务器地址 即上传图片后台接口的路径
      loading: '',
      param: {
        token: ''
      },
      dialogImageUrl: "",
      dialogImgVisible: false,
      disabled: false,
      imgs:[],
      num:0,
      fileNum:0
    }
  },
  computed: {
    // ['xxx', 'xxx'] 转换为 [{url: 'xxx'}, {url: 'xxx'}]
    fileList() {
      return this.value.map(url => ({
        url
      }))
    }
  },
  methods: {
    handlePictureCardPreview: function(file) {
      this.dialogImageUrl = file.url;
      this.dialogImgVisible = true;
    },
    handleRemove: function(file, fileList) {
      // fileList 为删除后的文件列表
      const value = fileList.map(v => v.url)
      this.$emit('input', value)
    },
    handleGoodsImagesUploadSuccess(response, file, fileList) {
      debugger
      console.log(response);
      console.log(fileList);

      if (response.code == 0) {
        debugger;
        let imageUrl = response.data.url;
        this.imgs.push(imageUrl);
        this.num++;
        if(this.num == this.fileNum){
          this.num = 0;
          this.fileNum = 0;
          // 这里如果 this.value.push(imageUrl) 这么写,vue会报出警告,大概意思是value作为props不应该在子组件中被修改
          // 应该根据 value 得到新的值,而不能修改它,this.value.concat(imageUrl)也是可以的,concat方法返回新的数组
          // this.$emit('input', [...this.value, imageUrl])
          this.$emit('input', this.value.concat(this.imgs))
          this.imgs =[];
        }
      } else {
        this.$message.error(file.name + '上传失败!');
      }
    },
    handlebeforeUpload(file) {
      // 这里做可以做文件校验操作
      const isImg = /^image\/\w+$/i.test(file.type)
      if (!isImg && this.fileType == 'image/*') {
        this.$message.error('只能上传 JPG、PNG、GIF 格式!')
        return false
      }
      this.fileNum++;
      console.log(this.fileNum);
    },
    handleUploadExceed() {
      this.$message.error(`最多上传${this.limit}张图片`)
    },
  }
}
script>
<style>
/*去除upload组件过渡效果*/
.el-upload-list__item {
  transition: none !important;
}
style>
<style scoped lang="scss">


.hide>>>.el-upload--picture-card {
  display: none;
}
style>

业务端的使用
自定义vue组件--实现多图片上传_第1张图片
自定义vue组件--实现多图片上传_第2张图片

三 后端代码实现

根据自己的后端代码具体实现,这里不做过多阐述

@RestController
@AllArgsConstructor
@RequestMapping("/sys-file")
@Api(value = "sys-file", tags = "文件管理")
public class SysFileController {

    private final SysFileService sysFileService;
    /**
     * 上传文件 文件名采用uuid,避免原始文件名中带"-"符号导致下载的时候解析出现异常
     *
     * @param file 资源
     * @return R(/ admin / bucketName / filename)
     */
    @PostMapping(value = "/upload")
    @Inner(value = false)
    public R upload(@RequestPart("file") MultipartFile file) {
        return sysFileService.uploadFile(file);
    }

    /**
     * 获取文件
     *
     * @param bucket   桶名称
     * @param fileName 文件空间/名称
     * @param response
     * @return
     */
    @Inner(false)
    @GetMapping("/{bucket}/{fileName}")
    public void file(@PathVariable String bucket, @PathVariable String fileName, HttpServletResponse response) {
        sysFileService.getFile(bucket, fileName, response);
    }
}

注意事项:

  • 后端接受图片的参数类型为String数组
  • 将组件中token和upload修改为自己项目本身的路径

四 基于mybatis的BaseTypeHandler实现自定义数据类型间的转换

mybatis为我们提供了个BaseTypeHandler的抽象类,可以帮助我们实现java类型和数据库之间相互类型的转换,我们知道String数组并并没有相对应的数据库字段类型,我们可以把他转换成以逗号相隔的字符串保存在数据库中,在java实体类映射转换时,又将其转换成相应的String数组

具体实现逻辑如下:

/**
 * Mybatis数组,符串互转
 * 

* MappedJdbcTypes 数据库中的数据类型 MappedTypes java中的的数据类型 * * @author likun * @date 2021-11-20 */ @MappedTypes(value = { String[].class }) //java实体类数据类型 @MappedJdbcTypes(value = JdbcType.VARCHAR) // 数据库里面对应字段的类型 public class JsonStringArrayTypeHandler extends BaseTypeHandler<String[]> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, ArrayUtil.join(parameter, StrUtil.COMMA)); } @Override @SneakyThrows public String[] getNullableResult(ResultSet rs, String columnName) { String reString = rs.getString(columnName); return Convert.toStrArray(reString); } @Override @SneakyThrows public String[] getNullableResult(ResultSet rs, int columnIndex) { String reString = rs.getString(columnIndex); return Convert.toStrArray(reString); } @Override @SneakyThrows public String[] getNullableResult(CallableStatement cs, int columnIndex) { String reString = cs.getString(columnIndex); return Convert.toStrArray(reString); } }

查看转换结果
在这里插入图片描述
自定义vue组件--实现多图片上传_第3张图片

你可能感兴趣的:(前端,vue.js,前端,javascript,java)