图片自定义上传和删除

536 阅读2分钟

图片自定义上传和删除

图片自定义上传和删除。使用 Ant Design Vue 快速实现图片的上传校验和接口返回处理,实现简单的业务头像或者项目缩略图组件。

有时候业务的上传接口和其他接口都需要鉴权,所以不能直接套用UI组件库的实例,所以需要自定义上传文件。

image.png

框架

  • Ant Design Vue
  • Vue3

核心函数

校验文件格式

上传文件之前的钩子。这里主要校验上传的图片的大小和格式。

const beforeUpload = file => {
  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
  if (!isJpgOrPng) {
    message.error('You can only upload JPG file!');
  }
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isLt2M) {
    message.error('Image must smaller than 2MB!');
  }
  return isJpgOrPng && isLt2M;
};

提示,添加 accept="image/*" 可以在前端限制用户上传的格式,比如这段代码就可以让用户在上传文件的系统弹窗中只显示图片类文件,虽然他们还是可以手动改变。所以 beforeUpload 是非常必要的。

获取上传后地址

需要把用户本地的图片,上传到我们的服务器上,并从中拿回展示的图片地址。通过 customRequest 方法,可以覆盖默认的上传行为,自定义自己的上传实现,并且处理上传中和上传失败等状态。

const customRequest = async info => {
  try {
    loading.value = true
    const res = await uploadFileRequest(info.file)
    imageUrl.value = res.url
    message.success('上传成功');
  } catch (err) {
    console.log('err', err)
    imageUrl.value = ''
    message.error('上传失败');
  } finally {
    loading.value = false
  }
}

完整代码

<template>
  <a-upload
    name="avatar"
    list-type="picture-card"
    class="avatar-uploader"
    accept="image/*"
    :show-upload-list="false"
    :before-upload="beforeUpload"
    :custom-request="customRequest"
  >
    <template v-if="imageUrl" >
      <img :src="imageUrl" class="avatar-img" alt="avatar" />
      <close-outlined 
        class="avatar-close" 
        title="删除"
        @click.stop="handleRemove"
      ></close-outlined>
    </template>
    <div v-else>
      <loading-outlined v-if="loading"></loading-outlined>
      <plus-outlined v-else></plus-outlined>
      <div class="ant-upload-text">上传图片</div>
    </div>
  </a-upload>
</template>
<script>
import { CloseOutlined, PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import { defineComponent, ref } from 'vue';
export default defineComponent({
  components: {
    CloseOutlined,
    LoadingOutlined,
    PlusOutlined,
  },
  setup() {
    const loading = ref(false);
    const imageUrl = ref('');
    // 实际请求接口处理
    const uploadFileRequest = file => {
      return new Promise((resolve) => {
        setTimeout(() => {
          // 模拟图片
          const mockUrl = 'https://www.dute.org/imgplaceholder/400x400'  
          resolve({ url: mockUrl })
        }, 1000);
      })
    }
    // 自定义请求
    const customRequest = async info => {
      try {
        loading.value = true
        const res = await uploadFileRequest(info.file)
        imageUrl.value = res.url
        message.success('上传成功');
      } catch (err) {
        console.log('err', err)
        imageUrl.value = ''
        message.error('上传失败');
      } finally {
        loading.value = false
      }
    }
    // 校验图片信息
    const beforeUpload = file => {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      if (!isJpgOrPng) {
        message.error('You can only upload JPG file!');
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        message.error('Image must smaller than 2MB!');
      }
      return isJpgOrPng && isLt2M;
    };
    const handleRemove = () => {
      imageUrl.value = ''
    }
    return {
      loading,
      imageUrl,
      handleRemove,
      customRequest,
      beforeUpload,
    };
  },
});
</script>
<style>
.avatar-uploader > .ant-upload {
  width: 128px;
  height: 128px;
  overflow: hidden;
  position: relative;
}
.avatar-img {
  width: 100%;
  height: 100%;
}
.avatar-close {
  position: absolute;
  right: 10px;
  top: 10px;
}
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
</style>