• vue封装ali-oss sdk web直传批量上传等
  • Artiely
  • #vue#ali-oss#plupload
  • 2020-05-22
  • 624
  • 4 min read
  • loading...

封装plupload实现web直传阿里OSS,并实现批量上传

本讲解只包含前端实现和后端实现飞机票

如何基于POST Policy的使用规则在服务端通过各种语言代码完成签名

对应的官方文档地址

图片直传实践

获取鉴权

export function getToken(currfile, base64) {
  return new Promise((resolve, reject) => {
    let type = currfile.type.split('/')[1]
    let fileType = type === 'mpeg' ? 'mp3' : type ? type : 'png'
    axios({
      method: 'POST',
      data: {
        parentFolderID: 0,
        userID: 1,
        fileType: fileType,
        fileOriName: currfile.name,
      },
      url: tokenUrl,
    })
      .then(final => {
        let res = final.data
        if (res.result) {
          let postData = {
            name: res.fileName,
            key: res.dir + res.fileName,
            policy: res.policy,
            OSSAccessKeyId: res.accessID,
            host: res.host,
            callback: res.callback,
            signature: res.signature,
            success_action_status: '200', // 让服务端返回200,不设置则默认返回204
            file: base64,
          }
          resolve(postData)
        } else {
          reject(final)
          console.log(final)
        }
      })
      .catch(e => {
        reject(e)
        console.log('getToken -> e', e)
      })
  })
}
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

上传图片

// 上传封面
export function postCover(postData) {
  return new Promise((resolve, reject) => {
    let formData = new FormData()
    formData.append('name', postData.name)
    formData.append('key', postData.key)
    formData.append('policy', postData.policy)
    formData.append('OSSAccessKeyId', postData.OSSAccessKeyId)
    formData.append('success_action_status', 200)
    formData.append('callback', postData.callback)
    formData.append('signature', postData.signature)
    formData.append('file', dataURLtoBlob(postData.file))

    axios({
      url: postUrl,
      data: formData,
      method: 'POST',
    })
      .then(final => {
        let res = final.data
        if (res.result) {
          resolve(res)
        } else {
          reject(res)
        }
      })
      .catch(e => {
        reject(e)
      })
  })
}
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

借助plupload实现上传进度

官网

// plupload初始化
    init() {
      const vm = this
      vm.uploader = new this.plupload.Uploader({
        runtimes: 'html5',
        browse_button: vm.$refs.btn,
        drop_element: vm.$refs.btn,
        multi_selection: false,
        multipart: true, // 已表单的方式上传
        auto_start: true,
        url: vm.postUrl,
        max_retries: 3,
        unique_names: true,
        filters: {
          mime_types: vm.mime_types,
          max_file_size: vm.maxFileSize, // 最大只能上传3gb的文件
          prevent_duplicates: true, // 不允许选取重复文件
        },

        init: {
          // 进度
          UploadProgress: function(up, file) {
            console.log('init -> up, file', file.percent) 
            vm.$emit('UploadProgress', { up, file })
          },
          // 添加成功
          FilesAdded: function(up, file) {
            let finalFile = file.map(v => {
              let currfile = v.getNative()
              let blob = new Blob([currfile], {
                type: currfile.type,
              }) // 传入一个合适的 MIME 类型
              let currentFileUrl = URL.createObjectURL(blob)
              vm.currentFile = currfile
              return {
                currentFileUrl,
                currfile,
              }
            })

            vm.$emit('FilesAdded', { up, file, finalFile })
          },
          // 上传成功
          FileUploaded: function(up, file, info) {
            try {
              const res = JSON.parse(info.response)
              vm.ossResult = res
              if (res.result) {
                vm.responseFileUrl = res.fileUrl
                vm.$emit('FileUploaded', {
                  up,
                  file,
                  info,
                  fileId: res.fileID,
                  responseFileUrl: vm.responseFileUrl,
                })
              } else {
                console.error('上传失败')
              }
            } catch (e) {
              console.error(e)
            }
          },
          Error: function(up, err) {
            vm.$emit('Error', { up, err })
          },
        },
      })
      vm.uploader.init()
    },
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

实现文件的批量上传

由于ali的web直传不支持批量上传,这里的原理就是多个实例去上传

// gettoken
    getToken(currfile, file) {
      let vm = this
      let upp = new vm.plupload.Uploader({
        runtimes: 'html5',
        browse_button: vm.$refs.ott,
        url: postUrl,
        multipart: true, // 已表单的方式上传
        header: {
          'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
        },
        unique_names: true,
        filters: {
          mime_types: vm.mime_types,
          max_file_size: vm.maxFileSize, // 最大只能上传3gb的文件
          prevent_duplicates: true, // 不允许选取重复文件
        },
        init: {
          FileUploaded: function(up, file, info) {
            try {
              const res = JSON.parse(info.response)
              vm.ossResult = res
              if (res.result) {
                vm.$emit('fileUploaded', {
                  up,
                  file,
                  info,
                  fileId: res.fileID,
                  responseFileUrl: res.fileUrl,
                })
              } else {
                console.error('上传失败')
              }
            } catch (e) {
              console.error(e)
            }
          },
          UploadProgress: function(up, file) {
            vm.$emit('uploadProgress', { file })
          },
        },
      })
      upp.init()
      upp.addFile(file)
      getToken(currfile).then(postData => {
        console.log(new Date().getTime())
        upp.setOption('multipart_params', {
          ...postData,
        })
        upp.start()
      })
    },
    // plupload初始化
    init() {
      const vm = this
      vm.uploader = new this.plupload.Uploader({
        runtimes: 'html5',
        browse_button: vm.$refs.btn,
        drop_element: vm.$refs.btn,
        multi_selection: vm.multiSelection,
        max_retries: 3,
        unique_names: true,
        filters: {
          mime_types: vm.mime_types,
          max_file_size: vm.maxFileSize, // 最大只能上传3gb的文件
          prevent_duplicates: true, // 不允许选取重复文件
        },
        init: {
          FilesAdded: function(up, files) {
            vm.plupload.each(files, file => {
              let currfile = file.getNative()
              let blob = new Blob([currfile], {
                type: currfile.type,
              }) // 传入一个合适的 MIME 类型
              let currentFileUrl = URL.createObjectURL(blob)
              vm.$emit('fileAdded', { file, currfile, currentFileUrl })
              vm.getToken(currfile, file)
            })
            let finalFile = files.map(v => {
              let currfile = v.getNative()
              let blob = new Blob([currfile], {
                type: currfile.type,
              }) // 传入一个合适的 MIME 类型
              let currentFileUrl = URL.createObjectURL(blob)
              return {
                currentFileUrl,
                currfile,
              }
            })
            vm.$emit('filesAdded', { up, files, finalFile })
          },
          Error: function(up, err) {
            vm.$emit('error', { up, err })
          },
        },
      })
      vm.uploader.init()
    },
复制成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98