antd上传单张多张图片 预览和删除

图片上传(有后台接口)

express框架+multer写的:https://www.cnblogs.com/catherLee/p/13141231.html

vue+koa框架写的:https://www.cnblogs.com/threepigs/p/10703689.html

https://www.cnblogs.com/miaSlady/p/13218319.html

下面这个有入口文件说明,搭配上面的搭建node服务

参考

以下代码块都是用的 formdata 方式上传图片

开发中用到的单张图片上传代码块(这是不带预览和删除的、比较简单)

 <a-upload 
	name="avatar" 
	list-type="picture-card" 
	:show-upload-list="false" 
	:action="uplodFiles">
     <img v-if="model.url" :src="model.url" alt="avatar" class="img-item" />
       <div v-else>
         <a-icon :type="loading ? 'loading' : 'plus'" />
         <div class="ant-upload-text">上传</div>
       </div>
 </a-upload>   

async uplodFiles(files) {
      this.loading = true
      let formData = new FormData()
      formData.append('files', files)
      //console.log('formData', formData.get('files'))
      const res = await uploadAction(this.url.uplodFiles, formData)
      this.loading = false
      this.model.url = res
   },

多张图片上传代码块(用的传统http-request方法)

参考

//element-ui图片多个上传完整代码
<el-upload
 action=""
 ref="upload"
 multiple
 :limit="3"
 list-type="picture-card"
 :auto-upload="false"
 :http-request="httpUploadFile"
 :on-change="codeChange"
 v-loading="codeLoding"
>
<i slot="default" class="el-icon-upload2"></i>
 <div slot="file" slot-scope="{ file }">
 <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
 <span class="el-upload-list__item-actions">
  <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
   <i class="el-icon-zoom-in"></i>
  </span>
  <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
   <i class="el-icon-delete"></i>
 </span>
</span>
</div>
</el-upload>

<el-button class="el-btn" @click="uploadClick">提交</el-button>
<a-modal centered :visible="previewVisible" :footer="null" @cancel="previewVisible = false">
 <img width="100%" :src="dialogImageUrl" alt="" />
</a-modal>


data() {
    return {
        url: {
          uplodUrl: '/pat/Snapshota/fileUpload',
      	},
        loading: false,
        previewVisible: false,
        disabled: false,
        dialogImageUrl: '',
     	fileList: [],
      	hasfileUrl: false,
    }
}

//改变了触发
codeChange(file) {
console.log('改变', file)
   if (file.url !== '') {
     this.hasfileUrl = true
   }
},
//点击提交触发
httpUploadFile(files) {
  this.fileList.push(files.file)
  console.log('请求后', this.fileList)
},
//提交上传
uploadClick() {
 if (this.hasfileUrl === false) {
   return this.$message.warning('请先选择图片')
 }
 let formData = new FormData()
 this.$refs.upload.submit()
 this.fileList.forEach((item) => {
   formData.append('files', item)
 })
 this.codeLoding = true
 uploadAction(this.url.uplodUrl, formData).then((res) => {
   this.model.picDetails = res
   console.log('上传成功', res)
   this.codeLoding = false
   this.$message.success('上传成功')
 })
},
//预览
handlePictureCardPreview(files) {
  console.log('预览', files)
  this.dialogImageUrl = files.url
  this.previewVisible = true
},
//移除
handleRemove(file) {
  let index = this.fileList.findIndex((item) => {
    return item.uid === file.raw.uid
  })
  this.fileList.splice(index, 1)
  console.log(this.fileList)
  this.$refs.upload.handleRemove(file)
},
// 表单和图片一起用自定义上传formData、append的方式传给后端、接口要设置contentType: "multipart/form-data",
// 这种方法是上传到服务器上、.env.development、.env.production、.env.staging都配置了
//# 图片路径前缀
//VUE_APP_IMG_BASE_API = 'http://192.168.3.73:8080/'

# 注意假如是用组件的自动上传要带上 :headers 自动上传会触发 :on-success
 headers: {
   'Content-Type': 'multipart/form-data',  // 上传文件的表单要加上请求头multipart/form-data
   // 或者这样写 ContentType: "multipart/form-data", Authorization: "Bearer " + getToken(),
 },

<el-upload
  action="#"
  ref="uploadImg"
  list-type="picture-card"
  :limit="1"
  :auto-upload="false"
  :http-request="httpUploadFile"
  :on-exceed="uploadExceed"
  :file-list="fileList"
>
  <i slot="default" class="el-icon-plus"></i>
  <div slot="file" slot-scope="{ file }">
    <img
      class="el-upload-list__item-thumbnail"
      :src="file.url"
      alt=""
    />
    <span class="el-upload-list__item-actions">
      <span
        v-if="!disabled"
        class="el-upload-list__item-delete"
        @click="handleRemove(file)"
      >
        <i class="el-icon-delete"></i>
      </span>
    </span>
  </div>
</el-upload>


 /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          this.elLoading = true;
          let formData = new FormData();
          // 假如有上传图片、调用上传方法、并添加上传的文件
          this.$refs.uploadImg.submit();
          if (this.file === null) {
            return this.$modal.msgError("请上传图标");
          }
          let newForm = {
            name: this.form.name,
            unit: this.form.unit,
            points: this.form.points,
            comment: this.form.comment,
          };
          for (let obj in newForm) {
            formData.append(obj, newForm[obj]);
          }
          formData.append("file", this.file);

          if (this.form.id != null) {
            formData.append("id", this.form.id);
            this.editForm(formData); // 编辑
          } else {
            this.addForm(formData); // 增加
          }
        }
      });
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset();
      const id = row.id || this.ids;
      this.elLoading = true;
      getSafflower(id).then((response) => {
        this.elLoading = false;
        this.form = response.data;
        this.open = true;
        this.title = "修改红花设置";
      });
      // 每次点击修改给fileList赋值
      this.fileList = [
        {
          name: this.publicGetUrlMethods(row.url),
          url: this.getTableUrl(row.url),
        },
      ];
    },
    // 公共获取图片后缀方法
    publicGetUrlMethods(url) {
      let index = url.lastIndexOf("/");
      return url.substr(index + 1);
    },
     // 转换成后台接口
    getTableUrl(url) {
      return VUE_APP_IMG_BASE_API + url;
    },
//element组件的自动上传 代码块
<el-upload
  ref="uploadImg"
  :action="articleAction"
  :limit="1"
  :headers="headersObj"
  :before-upload="beforeUpload"
  :on-exceed="uploadExceed"
  :on-success="uploadSuccess"
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :file-list="fileList"
>
  <el-button
    type="info"
    plain
    icon="el-icon-upload"
    size="mini"
    :disabled="isLocked"
  >
    上 传
  </el-button>
</el-upload>

<script>  
        
 export default {
	data() {
        return {
  			articleAction: process.env.VUE_APP_BASE_API + "/zhxy/network/upload",
  			headersObj: {
  			  ContentType: "multipart/form-data",
  			  Authorization: "Bearer " + getToken(),
  			},
  			// 锁
  			isLocked: false,
         }
  	},
    
 methods: {
      // 上传限制数量
    uploadExceed() {
      return this.$modal.msgWarning("只能上传一张图片");
    },
    // 上传之前
    beforeUpload(file) {
      if (this.isLocked) {
        return;
      }
      this.isLocked = true;
    },
    // 上传成功
    uploadSuccess(res, file, fileList) {
      console.log("上传成功", res);
      this.fileList = [
        {
          name: file.name,
          url: res.msg,
        },
      ];
      if (res.code == 200) {
        this.isLocked = false;
        return this.$modal.msgSuccess("上传成功");
      }
    },
    // 移除
    handleRemove(file) {
      console.log("移除", file);
      this.fileList = [];
    },
    // 预览
    handlePreview(file) {
      console.log("预览", file);
      this.pictureUrl = file.url;
      window.open(file.url);
    },
 }
</script>   

antd组件中实际上传图片并能 预览和删除 的代码块

参考:要求传文件上传token和file

formData.append('file', info.file)
formData.append('upload_token', res)
:customRequest="onUpload" // 自定义上传、
// 带Token  :headers = { Authorization: 'Bearer' + getToken() }
headers: {
   'Content-Type': 'multipart/form-data',  // 上传文件的表单要加上请求头multipart/form-data
},
也可以直接这么写:contentType: "multipart/form-data", 这里注意两种写法都要写在data之前

// 封装的图片上传接口
export function uploadAction(url,parameter){
  return axios({
    url: url,
    data: parameter,
    method:'post' ,
    headers: {
      'Content-Type': 'multipart/form-data',  // 文件上传
    },
  })
}

// 在Jeecg生成的代码中二次修改(单张上传)、这里没有引入它封装的JImageUpload.vue、这个组件是上传到服务器文件夹中 
<a-upload
  class="avatar-uploader"
  list-type="picture-card"
  :multiple="false"
  :file-list="fileList"
  :action="uploadImg"
  @change="handleChange"
  @preview="handlePreview"
  :class="[fileList.length < 1 ? '' : 'image-upload-single-over']"
>
  <div v-if="fileList.length < 1">
    <a-icon :type="fileLoading ? 'loading' : 'plus'" />
    <div class="ant-upload-text">上传</div>
  </div>
  <a-modal 
    :visible="previewVisible" 
    :footer="null" 
	@cancel="previewVisible = false" 
    :closable="false"
  >
   <img alt="example" style="width: 100%" :src="previewImage" />
  </a-modal>
</a-upload>


<script>
 import { uploadAction } from '@/api/manage'
 // 不重复的负数uid方法(antd上传组件的fileList要用到)
 const uidGenerator = () => {
   return '-' + parseInt(Math.random() * 10000 + 1, 10)
 }
 // 不重复的name方法
 const getFileName = (path) => {
   if (path.lastIndexOf('\\') >= 0) {
     let reg = new RegExp('\\\\', 'g')
     path = path.replace(reg, '/')
 }
 return path.substring(path.lastIndexOf('/') + 1)
 }
export default {
  data() {
      url: {
        uploadUrl: '/pat/Snapshota/fileUpload',
      },
      fileLoading: false,
      model: {},
      fileList: [],
      previewVisible: false,
      previewImage: ''
  }
  methods() {
  // 单张图片上传↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  uploadImg(file) {
    this.fileLoading = true
    let formData = new FormData()
    // PS: 后端接口参数是files
    formData.append('files', file)
    uploadAction(this.url.uploadUrl, formData).then((res) => {
      this.fileLoading = false
      // 上传成功之后将oss返回的url赋值到表单model的 pictureUrl上来提交
      this.model.pictureUrl = res
      // 转数组
      let arr = file.name.split(',')
      let fileList1 = []
      for (var i = 0; i < arr.length; i++) {
        fileList1.push({
          uid: uidGenerator(),
          name: getFileName(arr[i]),
          status: 'done',
          url: res,
        })
        this.fileList = fileList1
      }
    })
    },
    handlePreview(file) {
      this.previewImage = file.url
      this.previewVisible = true
    },
    // 改变时触发
    handleChange({ file }) {
      if (file.status === 'removed') {
        this.fileList.splice(this.fileList.indexOf(file), 1)
        // PS: 每次删除之后要把对应的pictureUrl去除、不然提交的数据没有变化
        this.model.pictureUrl = ''
      }
    },
    // 单张图片上传↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    // jeecg封装表格当前行的编辑按钮触发方法
    edit(record) {
      this.model = Object.assign({}, record)
      this.visible = true
       // 假如本行数据拿到了record.pictureUrl 阿里oss传回来的url,那么给fileList重新赋值、编辑回显出图片
       // antd预览的图片是通过绑定的 fileList 来决定的、要遵循官方给的格式
       if (record.pictureUrl) {
        let fileList1 = []
        let arr = record.id.split(',')
        for (var i = 0; i < arr.length; i++) {
          fileList1.push({
            uid: uidGenerator(),
            name: getFileName(arr[i]),
            status: 'done',
            url: record.pictureUrl,
          })
        }
        this.fileList = fileList1
      }
    }
   },
  }
</script>
<style scoped lang="less">
.img-item {
  width: 100px;
  height: 100px;
}

// 这里是用来控制单张图片上传后禁用上传的框
/deep/ .image-upload-single-over .ant-upload.ant-upload-select-picture-card {
  display: none;
}
</style> 
//多张上传预览和删除代码块、和上面单张上传差不多、区别在于这里限制了多张上传
//因为限制最多上传三张、为了防止出bug、设置了 :multiple="false"
<a-upload
  class="avatar-uploader"
  list-type="picture-card"
  :multiple="false"
  :file-list="detailFileList"
  :action="uploadDetail"
  @change="handleDetailChange"
  @preview="handleDetailPreview"
 >
 <div>
   <a-icon :type="detailLoading ? 'loading' : 'plus'" />
   <div class="ant-upload-text">上传</div>
 </div>
 <a-modal 
   :visible="detailPreviewVisible" 
   :footer="null" 
   @cancel="detailPreviewVisible = false" 
   :closable="false">
   <img alt="example" style="width: 100%" :src="detailPreviewImage" />
 </a-modal>
</a-upload>

<script>
import { uploadAction } from '@/api/manage'
 // 不重复的负数uid方法(antd上传组件的fileList要用到)
 const uidGenerator = () => {
   return '-' + parseInt(Math.random() * 10000 + 1, 10)
 }
 // 不重复的name方法
 const getFileName = (path) => {
   if (path.lastIndexOf('\\') >= 0) {
     let reg = new RegExp('\\\\', 'g')
     path = path.replace(reg, '/')
 }
 return path.substring(path.lastIndexOf('/') + 1)
 }
export default {
  data() {
      url: {
        uploadUrl: '/pat/Snapshota/fileUpload',
      },
      // 多张上传url暂存变量
      allUrl: [],
      detailFileList: [],
      detailPreviewVisible: false,
      detailLoading: false,
      detailPreviewImage: '',
  },
  methods: {
     edit(record) {
       this.model = Object.assign({}, record)
       this.visible = true
       // 假如有record.picDetails、批量给 detailFileList赋值
       if (record.picDetails) {
        let arr = record.picDetails.split(',')
        for (var i = 0; i < arr.length; i++) {
          this.detailFileList.push({
            uid: uidGenerator(),
            name: getFileName(arr[i]),
            status: 'done',
            url: arr[i],
          })
        }
        // 点击编辑也要给picDetails赋值
        this.detailFileList.filter((item) => {
          that.allUrl.push(item.url)
        })
        // PS: 这里必须重新赋值picDetails、不然回显删除在上传提交有bug
        this.model.picDetails = this.allUrl.join(',')
        console.log('点击了编辑的detailFileList', this.detailFileList)
        console.log('点击了编辑的picDetails', this.model.picDetails)
      }
     },
     // 多张上传↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
     uploadDetail(file) {
       this.detailLoading = true
       let formData = new FormData()
       formData.append('files', file)
       if (this.detailFileList.length === 3) {
         this.detailLoading = false
         return this.$message.warning('最多只能上传三张详情图片')
       }
       uploadAction(this.url.uploadUrl, formData).then((res) => {
         this.detailLoading = false
         this.allUrl.push(res)
         this.model.picDetails = this.allUrl.join(',')
         this.detailFileList.push({
           uid: uidGenerator(),
           name: getFileName(file.name),
           status: 'done',
           url: res,
         })
         console.log('上传成功的detailFileList', this.detailFileList)
       })
     },
     handleDetailPreview(file) {
       let [{ url }] = this.detailFileList.filter((item) => {
         return item.uid === file.uid
       })
       this.detailPreviewImage = url
       this.detailPreviewVisible = true
     },
     handleDetailChange({ file }) {
       if (file.status === 'removed') {
         let delItem = this.detailFileList.filter((item) => {
           return item.uid === file.uid
         })
         // 转数组
         let picUrl = this.model.picDetails.split(',')
         let index = picUrl.indexOf(delItem[0].url)
         this.detailFileList.splice(index, 1)
         picUrl.splice(index, 1)
         // 转字符串
         this.model.picDetails = picUrl.join(',')
         console.log('删除之后的detailFileList', this.detailFileList)
         console.log('删除之后的picDetails', this.model.picDetails)
       }
     },
     // 多张上传↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
  } 
</script>
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只管挖坑不管埋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值