upload.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import OSS from 'ali-oss'
  2. import { v4 as uuidv4 } from 'uuid'
  3. class OssUploadUtils {
  4. constructor(app, callback = {}) {
  5. this.app = app // vue实例
  6. this.client = null // ossClient
  7. this.baseFileUrl = '' // 文件上传根路径
  8. this.callback = callback
  9. this.fileList = [] // 上传文件列表
  10. }
  11. // 初始化oss client实例
  12. async initOssClient() {
  13. try {
  14. const res = await this.app.$http.api.fetchOssInit()
  15. if (res.code) return
  16. const { accessKeyId, securityToken, bucket, accessKeySecret } = res.data
  17. const config = {
  18. // 以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  19. region: 'oss-cn-shenzhen',
  20. accessKeyId,
  21. accessKeySecret,
  22. stsToken: securityToken,
  23. bucket,
  24. }
  25. this.client = new OSS(config)
  26. this.baseFileUrl = `https://${config.bucket}.${config.region}.aliyuncs.com/`
  27. setInterval(() => {
  28. this.initOssClient()
  29. }, 1000 * 60 * 60)
  30. return res
  31. } catch (error) {
  32. return error
  33. }
  34. }
  35. // 取消上传
  36. abortMultipartUpload(abortCheckpoint) {
  37. this.client.abortMultipartUpload(
  38. abortCheckpoint.name,
  39. abortCheckpoint.uploadId
  40. )
  41. }
  42. // 上传文件
  43. async multipartUpload(rawFile) {
  44. if (!this.client) {
  45. await this.initOssClient()
  46. }
  47. if (rawFile.status > -1) return
  48. try {
  49. // 指定上传到examplebucket的Object名称,例如exampleobject.txt。
  50. rawFile.bucketName = this.generateFileName(rawFile)
  51. rawFile.uuid = this.formatOssName(rawFile)
  52. // 分片上传
  53. const res = await this.client.multipartUpload(
  54. rawFile.bucketName,
  55. rawFile.file,
  56. {
  57. // 获取分片上传进度、断点和返回值。
  58. progress: (p, cpt, res) => {
  59. this.onProgress(p, cpt, res, rawFile)
  60. },
  61. // 设置并发上传的分片数量。
  62. parallel: 10,
  63. // 设置分片大小。默认值为1 MB,最小值为100 KB。
  64. partSize: 1024 * 1024,
  65. // 文件类型
  66. mime: rawFile.file.type,
  67. headers: {
  68. // 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
  69. 'x-oss-forbid-overwrite': 'true',
  70. },
  71. }
  72. )
  73. this.onSuccess(res, rawFile)
  74. } catch (err) {
  75. this.onFaild(err, rawFile)
  76. console.log(err)
  77. }
  78. }
  79. // 上传文件
  80. upload(file) {
  81. const rawfile = this.generateRawfile(file)
  82. this.fileList.push(rawfile)
  83. this.multipartUpload(rawfile)
  84. }
  85. // 上传多个文件
  86. uploadAll(fileList) {
  87. fileList.forEach((file) => {
  88. const rawFile = this.generateRawfile(file)
  89. this.fileList.push(rawFile)
  90. this.multipartUpload(rawFile)
  91. })
  92. }
  93. // 监听上传进度
  94. onProgress(p, cpt, res, rawFile) {
  95. rawFile.status = 2
  96. rawFile.percentage = Math.ceil(p * 100)
  97. rawFile.checkpoint = cpt
  98. rawFile.response = res
  99. this.callback.progress && this.callback.progress(rawFile, this.fileList)
  100. }
  101. // 监听上传成功
  102. onSuccess(response, rawFile) {
  103. rawFile.status = 1
  104. rawFile.response = response
  105. rawFile.url = this.baseFileUrl + response.name
  106. this.callback.success && this.callback.success(rawFile, this.fileList)
  107. }
  108. // 监听上传失败
  109. onFaild(error, rawFile) {
  110. rawFile.response = error
  111. rawFile.status = 0
  112. this.callback.faild && this.callback.faild(rawFile, this.fileList)
  113. }
  114. // 处理上传文件名称
  115. generateFileName(rawfile) {
  116. const upload_dir = process.env.UPLOAD_DIR
  117. const name =
  118. upload_dir +
  119. rawfile.name.replace(/([^\\/]+)\.([^\\/]+)/i, (match, $1, $2) => {
  120. const lastName = rawfile.uuid + '.' + $2
  121. return lastName
  122. })
  123. return name
  124. }
  125. // 处理ossName
  126. formatOssName(rawfile) {
  127. const name = rawfile.name.replace(
  128. /([^\\/]+)\.([^\\/]+)/i,
  129. (match, $1, $2) => {
  130. const lastName = rawfile.uuid + '.' + $2
  131. return lastName
  132. }
  133. )
  134. return name
  135. }
  136. // 处理文件字段信息
  137. generateRawfile(file) {
  138. return {
  139. uuid: uuidv4(),
  140. name: file.name,
  141. file: file,
  142. percentage: 0,
  143. status: -1, // 0 上次失败 1 上传成功 2 上传中 -1 待上传
  144. url: '',
  145. response: null,
  146. checkpoint: null,
  147. }
  148. }
  149. }
  150. export default OssUploadUtils