正确使用element-ui 的上传组件upload完成自定义上传到阿里云oss云服务器或自己后台服务器

89 篇文章 7 订阅
43 篇文章 0 订阅

需求:使用element的upload组件,上传文件到阿里云服务器。上传前,先请求自己后台的接口,返回阿里云上传相关的凭证key等信息后才能正确上传。
那如何解决呢?
答案是element上传组件中的 http-request 自定义上传。

 <el-upload
  ref="upload"
  class="upload-demo"
  action
  :http-request="handleUpload"
  :auto-upload="false"
  multiple
  :on-exceed="handleExceed"
  :file-list="fileList"
  :on-change="onChangeFile"
  :on-remove="handleRemove"
  :on-preview="handlePreview"
  :before-remove="beforeRemove"
>
  <el-button slot="trigger" :disabled="type !== 'view' ? false : true" size="small" type="primary">选取文件</el-button>
  <el-button :disabled="type !== 'view' ? false : true" style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
</el-upload>

说明一下:
action设置为空,因为我们需要自己来控制上传。
:http-request=“handleUpload” 我们自己定义的上传方法。具体见后面。
:auto-upload=“false” 我关掉了选择文件后自动上传,改为手动触发。
:file-list=“fileList” 上传文件的文件列表
:on-change=“onChangeFile” 选择文件或是上传成功后都会触发,不仅仅是选择文件后触发。
其他看文档。没有什么好说的。

我在data中定义了两个文件列表相关的

data() {
return {
// 真实的附件列表,提交表单的时候,真实数据
      realFileList: [],
      // 上传文件列表,el-upload使用,临时保存数据。
      fileList: [
        // { name: 'aaa', url: 'image/196b62fd-fc70-4634-9bca'}
      ]}
}

fileList是给upload组件绑定使用的,没有上传的文件都会在里面
realFileList是上传成功后传递后台的文件列表数据。

为啥要分开呢? 因为fileList中,不好控制。选择文件后,没有上传,fileList中是没有的。上传成功后,fileList才会有数据。点击删除的时候,已经上传的fileList还是会保留数据,
这个原因导致我需要维护两个realFileList和fileList属性。

定义的methods中相关的上传函数

  methods: {
    // 选择上传文件,上传成功后都会出发
    onChangeFile(file, fileList) {
      console.log('选择文件', file, fileList)
      if (file.response) {
        // this.fileList.push(file.response)
        // 上传成功后,把成功的结果添加到realFileList中
        this.realFileList.push(file.response)
      }
    },
        // 自定义上次操作
    handleUpload(op) {
      // console.log('上传', op)
      // op是element返回的上传相关的东西,通过它可以操作很多东西,进度条什么的,可以打印出来看,有很多回调方法,
      // 这里的upload是我自己的封装的上传处理函数
      myupload(
        op.file,
        res => {
          let temp = {
            name: res.attachment,
            url: res.aliyunAddress
          }
          // 成功后的回调,把结果返回,并且把上传列表的状态改变,打上成功的√
          op.onSuccess(temp)
        },
        err => {
          console.log(err)
        },
        res => {
        // 处理进度条的东西,把进度数据传进去实现进度条走动,传参res应该是这样的类型{percent: 48}
          op.onProgress(res)
        }
      )
    },
        // 监听移除文件列表
    handleRemove(file, fileList) {
      // 删除的是未上传的文件
      console.log('删除文件', file, fileList)
      if (file.status === 'success') {
        this.realFileList.map((v, i, arr) => {
          if (v.url === file.url || v.url === file.response.url) {
            arr.splice(i, 1)
          }
        })
      }
    },
        // 预览(下载文件)
    handlePreview(file) {
      // console.log(file)
      // 没有上传成功,不可以预览
      if (file.status !== 'success') {
        return
      }
      let fileurl = file.url || file.response.url // 前者是获取详情回来的文件,后者是刚刚新上传成功的文件
      window.open(fileurl )
    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
    },
    beforeRemove(file) {
      return this.$confirm(`确定移除 ${file.name}?`)
    }

upload函数是我自定义的,使用axios实现的。具体内容如下:


// myupload.js
/*
 * @Description: 附件上传
 * @Autor: bolingsun
 * @Date: 2020-09-09 10:03:43
 */
import { v4 as uuidv4 } from 'uuid'
// import { fetchUploadPara } from '@/api/upload'
import axios from 'axios'
let basePath
if (process.env.NODE_ENV === 'production') {
  basePath = window.init_params.basePath
} else {
  basePath = '/portal/pages/vue/undefined'
}
/**
 * @description: 文件附件上传
 * file: 文件raw对象
 * successCallback: 成功的回调函数
 * errCallBack: 错误的回调函数
 * progressCallback: 上传进度的回调函数
 */
const myupload= function(file, successCallback = new Function(), errCallBack = new Function(), progressCallback = new Function()) {
  let fileName = file.name
  // options = options || {}
  axios({
    method: 'get',
    url: basePath + '/aliyun/get',
    params: {
      dir: 'image'
    }
  })
    .then(res => {
      let obj = res.data.data
      let config = {}
      config.host = obj['host']
      config.policyBase64 = obj['policy']
      config.accessid = obj['accessId']
      config.signature = obj['signature']
      config.expire = parseInt(obj['expire'])
      config.callbackbody = obj['callback']
      config.dir = obj['dir']
      let fd = new FormData(),
        uuid = uuidv4(),
        key = config.dir + uuid
      fd.append('key', key)
      fd.append('success_action_status', '200')
      fd.append('x-oss-object-acl', 'public-read')
      fd.append('x-oss-meta-fullname', fileName)
      fd.append('OSSAccessKeyId', config.accessid)
      fd.append('policy', config.policyBase64)
      fd.append('signature', config.signature)
      fd.append('success_action_status', '200')
      fd.append('file', file)
      if (config.host.indexOf('http:') > -1) {
        var protocol = window.location.protocol || 'http:'
        var subUrl = config.host.substring(5, config.host.length)
        config.host = protocol + subUrl
      }
      axios({
        url: config.host,
        method: 'POST',
        data: fd,
        processData: false,
        cache: false,
        contentType: false,
        onUploadProgress: function(progressEvent) {
          if (progressEvent.lengthComputable) {
            let percent = ((progressEvent.loaded / progressEvent.total) * 100) | 0
            progressCallback({ percent: percent })
          }
        }
      })
        .then(() => {
          let size = file.size > 1000000 ? parseFloat(file.size / 1000000).toFixed(2) + 'M' : parseFloat(file.size / 1000).toFixed(2) + 'KB'
          successCallback({
            attachment: fileName,
            aliyunAddress: key,
            size: size
          })
        })
        .catch(err => {
          errCallBack(err)
        })
    })
    .catch(err => {
      errCallBack(err)
      // console.log(err)
    })
}
export default myupload

具体内容大家就根据自己公司的情况去写具体的逻辑了。
我大概解释一下。

myupload= function(file, successCallback = new Function(), errCallBack = new Function(), progressCallback = new Function()) {

四个参数, file传入的是文件对象,他上面有二进制数据的。successCallback 是成功后的回调,errCallBack 是失败后的回调,progressCallback 是进度条的回调。
上传进度条,相关的是这个内容:

  axios({
        url: config.host,
        method: 'POST',
        data: fd,
        processData: false,
        cache: false,
        contentType: false,
        // 这个是axios关于上传进度的配置,progressEvent是原生的上传进度对象
        onUploadProgress: function(progressEvent) {
          if (progressEvent.lengthComputable) {
            let percent = ((progressEvent.loaded / progressEvent.total) * 100) || 0
            progressCallback({ percent: percent })
          }
        }
      })

在上传的过程中, 会触发progressEvent事件,我们把进度通过progressEvent.loaded / progressEvent.total计算出来后,通过progressCallback回调函数,把结果返回回去。

然后在element-ui upload的地方,使用。
op.onProgress({ percent: percent })
这样就可以顺利显示进度条啦。

补充说明一下关于element-ui upload的相关属性:

onChangeFile 这个是,你选择了两个文件,就会触发两次,上传成功了,也会触发。

handleUpload 这个是,你选择了两个文件,两个文件会先后依次调用这个方法。选择几个文件,点击上传操作,就会触发调用几次这个函数

handleRemove 这个是,你删除了没有上传成功的文件,就是删除了,但是,你删除上传成功了的文件,列表显示是不见了,但是 绑定fileList内,还是有数据的,没有真的删除掉。

还有一点,这个上传的本质,就是new FormData 实例化一个表单对象,把文件二进制数据,以表单的形式提交而已。就这么回事。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Element-UI 是一个基于 Vue.js 的组件库,提供了丰富的 UI 组件和交互功能。要实现在 Element-UI 中上图片到阿里 OSS,可以按照以下步骤进行: 1. 安装依赖:首先,需要安装 `ali-oss` 和 `element-ui` 的相关依赖。可以使用 npm 或者 yarn 进行安装。 2. 配置阿里 OSS:在阿里 OSS 控制台创建一个 Bucket,并获取 AccessKeyId、AccessKeySecret、Bucket 名称和 Endpoint。 3. 创建上组件:在 Vue 组件中,使用 Element-UI 的 `el-upload` 组件来实现图片上功能。可以设置 `action` 属性为阿里 OSS 的上地址,`before-upload` 属性来处理上前的逻辑。 4. 在上前进行签名:在 `before-upload` 方法中,需要通过阿里 OSS 的 SDK 进行签名操作,生成上所需的参数。可以使用 `ali-oss` 库提供的 `put` 方法来进行签名。 5. 上图片:在签名成功后,调用 `put` 方法将图片上到阿里 OSS。可以设置 `on-success` 属性来处理上成功后的逻辑。 下面是一个简单的示例代码: ```vue <template> <el-upload action="https://your-bucket-name.oss-cn-hangzhou.aliyuncs.com" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess" > <el-button>点击上</el-button> </el-upload> </template> <script> import OSS from 'ali-oss'; export default { methods: { async handleBeforeUpload(file) { const client = new OSS({ region: 'your-region', accessKeyId: 'your-access-key-id', accessKeySecret: 'your-access-key-secret', bucket: 'your-bucket-name', }); try { const result = await client.put(file.name, file); // 在这里可以处理上成功后的逻辑 } catch (error) { // 处理上失败的逻辑 } // 返回 false 可以阻止上 return false; }, handleUploadSuccess(response) { // 处理上成功后的逻辑 }, }, }; </script> ``` 请注意,上述代码中的 `your-region`、`your-access-key-id`、`your-access-key-secret` 和 `your-bucket-name` 需要替换为你自己的阿里 OSS 相关信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值