ali-oss-upload-mixins.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import {
  2. getUploadToken
  3. } from '@/api/webApi/common.js'
  4. import consts from '@/common/mx-const'
  5. import cacheMixin from './Cache/mx-cache-mixin'
  6. export default {
  7. mixins: [cacheMixin],
  8. model: {
  9. prop: 'value',
  10. event: 'input'
  11. },
  12. props: {
  13. // 值
  14. value: [String, Object, Array],
  15. // 大小限制(MB)
  16. fileSize: {
  17. type: Number,
  18. default: 1024
  19. },
  20. // 是否显示提示
  21. isShowTip: {
  22. type: Boolean,
  23. default: true
  24. },
  25. // upload type // 不同的类型将分放到不同目录
  26. type: {
  27. type: Number,
  28. default: consts.enum.uploadType.personalResource
  29. }
  30. },
  31. data() {
  32. return {
  33. // 改为OSS上传
  34. // uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
  35. // headers: {
  36. // Authorization: "Bearer " + getToken(),
  37. // },
  38. // 上传个数限制
  39. limit: 0,
  40. // 文件类型, 例如['png', 'jpg', 'jpeg']
  41. fileType: ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf', 'png', 'jpg', 'jpeg'], // 逻辑判断用
  42. uploading: false,
  43. uploadPercent: 0,
  44. ossRegion: 'oss-cn-beijing',
  45. ossBucket: 'mingxuejingbang',
  46. uploadFileTypes: this.mxGlobal.uploadFileTypes, // 打开窗口用,是标准化的文件类型名称,比较长不适合逻辑展示
  47. uploadTypes: [],
  48. fileList: []
  49. }
  50. },
  51. computed: {
  52. // 是否显示提示
  53. showTip() {
  54. return this.isShowTip && (this.fileType || this.fileSize)
  55. },
  56. // 列表
  57. list() {
  58. let temp = 1
  59. if (this.value) {
  60. // 首先将值转为数组
  61. const list = Array.isArray(this.value) ? this.value : [this.value]
  62. // 然后将数组转为对象数组
  63. return list.map((item) => {
  64. if (typeof item === 'string') {
  65. item = { name: item, url: item }
  66. }
  67. item.uid = item.uid || new Date().getTime() + temp++
  68. return item
  69. })
  70. } else {
  71. this.fileList = []
  72. return []
  73. }
  74. }
  75. },
  76. methods: {
  77. // 上传前校检格式和大小
  78. handleBeforeUpload(file) {
  79. // 校检文件类型
  80. if (this.fileType) {
  81. let fileExtension = ''
  82. if (file.name.lastIndexOf('.') > -1) {
  83. fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
  84. }
  85. const isTypeOk = this.fileType.some((type) => {
  86. if (file.type.indexOf(type) > -1) return true
  87. if (fileExtension && fileExtension.indexOf(type) > -1) return true
  88. return false
  89. })
  90. if (!isTypeOk) {
  91. this.$message.error(`文件格式不正确, 请上传${this.fileType.join('/')}格式文件!`)
  92. return false
  93. }
  94. }
  95. // 校检文件大小
  96. if (this.fileSize) {
  97. const isLt = file.size / 1024 / 1024 < this.fileSize
  98. if (!isLt) {
  99. this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
  100. return false
  101. }
  102. }
  103. // 校验存储目录
  104. if (!this.getSaveDir()) {
  105. this.$message.error(`上传文件存储路径未配置,请联系管理员!`)
  106. return false
  107. }
  108. return true
  109. },
  110. // 文件个数超出
  111. handleExceed() {
  112. this.$message.error(`只允许上传 ${this.limit} 个文件`)
  113. },
  114. // 上传失败
  115. handleUploadError(err) {
  116. this.$message.error('上传失败, 请重试')
  117. },
  118. // 上传成功回调
  119. handleUploadSuccess(res, file) {
  120. this.fileList.push(res)
  121. this.handleNotify()
  122. this.$message.success('上传成功')
  123. },
  124. // 删除文件
  125. handleDelete(file, fileList) {
  126. this.fileList = fileList
  127. this.handleNotify()
  128. },
  129. handleNotify() {
  130. this.$emit('input', this.fileList)
  131. },
  132. handleUpload(param) {
  133. getUploadToken().then(res => {
  134. // https://mingxuejingbang.oss-cn-beijing.aliyuncs.com/mingxueMainImgs/skld.png
  135. const OSS = require('ali-oss')
  136. const client = new OSS({
  137. // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
  138. // 从STS服务获取的安全令牌(SecurityToken)。
  139. accessKeyId: res.data.credentials.accessKeyId,
  140. accessKeySecret: res.data.credentials.accessKeySecret,
  141. stsToken: res.data.credentials.securityToken,
  142. secure: true,
  143. // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  144. // 填写Bucket名称,例如examplebucket。
  145. region: this.ossRegion,
  146. bucket: this.ossBucket
  147. })
  148. const file = param.file
  149. const lastIndexOfDot = file.name.lastIndexOf('.')
  150. const pureName = file.name.substring(0, lastIndexOfDot)
  151. const fileNameSuffix = file.name.substring(lastIndexOfDot)
  152. const ticket = new Date().getTime() // 防重名覆盖
  153. const storeAs = this.getSaveDir() + pureName + '.' + ticket + fileNameSuffix
  154. console.log('oss-client', client, param)
  155. this.uploading = true
  156. this.uploadPercent = 0
  157. this.$emit('uploadBegin')
  158. client.multipartUpload(storeAs, file, {
  159. progress: p => {
  160. const displayPercent = Math.ceil(p * 100)
  161. this.uploadPercent = displayPercent
  162. }
  163. }).then(result => {
  164. const standardResult = {
  165. name: pureName,
  166. url: `https://${this.ossBucket}.${this.ossRegion}.aliyuncs.com/${result.name}`,
  167. fileSize: file.size / 1024 / 1024, // 转MB
  168. isImage: file.type === 'image/jpeg' || file.type === 'image/jpg' || file.type === 'image/png'
  169. }
  170. param.onSuccess(standardResult)
  171. }).catch(err => {
  172. param.onError(err)
  173. }).finally(() => {
  174. setTimeout(_ => {
  175. this.uploading = false
  176. this.$emit('uploadEnd')
  177. }, 2000)
  178. })
  179. })
  180. },
  181. // 获取文件名称
  182. getFileName(name) {
  183. if (name.lastIndexOf('/') > -1) {
  184. return name.slice(name.lastIndexOf('/') + 1).toLowerCase()
  185. } else {
  186. return ''
  187. }
  188. },
  189. getSaveDir() {
  190. if (!this.uploadTypes.length) return ''
  191. let path = this.uploadTypes.find(t => t.value == this.type)?.label || ''
  192. if (path && !path.endsWith('/')) path += '/'
  193. return path
  194. }
  195. },
  196. async created() {
  197. this.fileList = this.list
  198. this.uploadTypes = await this.getFileUploadTypeListByCache()
  199. }
  200. }