自定义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>
<!--
	使用用例
	uploadEdit 是否启用编辑 true false
	fileType可以是
	audio/*表示“任何音频文件
	video/*表示“任何视频文件
	image/*表示“任何图像文件
	还可以以逗号拼接,如image/*,.pdf
	<multi-upload v-model="form.voucherUrlList" :fileType="image/*"></multi-upload>
	import MultiUpload from '@/components/Upload/MultiUpload'
	components: {
		MultiUpload
	},
-->


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

业务端的使用
在这里插入图片描述
在这里插入图片描述

三 后端代码实现

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

@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数组,符串互转
 * <p>
 * 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);
	}

}

查看转换结果
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值