当前位置:   article > 正文

Uniapp+vue3 APP上传图片到oss_uni.uploadfile put上传图片到oss

uni.uploadfile put上传图片到oss

开发工具:HBuilder(v3.8.7.20230703); 框架:uni-app(vue3);

 

由于第一次使用uniapp开发APP,开发中遇到app上传图片的问题,这个问题是困扰我时间最长的,查找了各种文章,所以记录一下。

大家肯定和我一样一开始都没有考虑,以为uni.uploadFile()可以直接上传到OSS,我替大家试了,不行。

原因:APP上传拿到的不是一个file格式数据,是一个app的临时链接,无法上传到oss,要转换为file格式才可以, 但是转file要使用nodejs中的内置模块,可能是uniapp没有加载nodejs内置模块无法使用,然后可以使用renderjs实现。

renderjs是一个运行在视图层的js, 它只支持app-vue和h5, 主要服务于APP。

  1. <template>
  2. <view>
  3. <uni-file-picker
  4. v-if="!slots.default"
  5. v-model="fileList"
  6. :limit="limit"
  7. :title="title"
  8. :readonly="disabled"
  9. @select="handleSelectImage"
  10. />
  11. // info:传到renderjs中的参数
  12. // change:info="uploadFile.tofile" 监听info的变化 。
  13. <view :info="uploadData" :change:info="uploadFile.tofile"></view>
  14. </view>
  15. </template>
  16. // service 层
  17. <script setup>
  18. </srcipt>
  19. // module:renderjs模块名称
  20. <script module="uploadFile" lang="renderjs">
  21. // data:info的新数据
  22. // oldValue: 旧数据
  23. // ownerInstance 可用来向service通信
  24. tofile (data, oldValue, ownerInstance) {}
  25. </srcipt>

以下是全部代码

  1. <template>
  2. <view>
  3. <uni-file-picker
  4. v-if="!slots.default"
  5. v-model="fileList"
  6. :limit="limit"
  7. :title="title"
  8. :readonly="disabled"
  9. @select="handleSelectImage"
  10. />
  11. <view :info="uploadData" :change:info="uploadFile.tofile"></view>
  12. </view>
  13. </template>
  14. <script setup>
  15. import { watchEffect, ref, useSlots, reactive } from 'vue'
  16. import { signatureKey } from '@/utils/ali-oss'
  17. import { getUploadPolicy } from '@/request/oss'
  18. const fileList = ref([])
  19. const uploadData = reactive({})
  20. const slots = useSlots()
  21. const isUpload = ref(false)
  22. const props = defineProps({
  23. modelValue: {
  24. type: String,
  25. default() {
  26. return ''
  27. }
  28. },
  29. fileType: {
  30. type: String,
  31. default() {
  32. return ''
  33. }
  34. },
  35. limit: {
  36. type: String,
  37. default() {
  38. return '1'
  39. }
  40. },
  41. title: {
  42. type: String,
  43. default() {
  44. return ''
  45. }
  46. },
  47. disabled: {
  48. type: Boolean,
  49. default() {
  50. return false
  51. }
  52. }
  53. })
  54. const emit = defineEmits(['update:modelValue', 'success'])
  55. const formatFiles = (modelValue) => {
  56. if (!modelValue) {
  57. return []
  58. }
  59. const fileList = modelValue.split(',')
  60. return fileList.map(item => {
  61. return {
  62. name: '',
  63. key: item,
  64. extname: 'png',
  65. url: signatureKey(item)
  66. }
  67. })
  68. }
  69. const handleSuccess = (data, url) => {
  70. fileList.value.push({
  71. name: '',
  72. url,
  73. key: data.key
  74. })
  75. const keyList = []
  76. fileList.value.forEach(item => {
  77. keyList.push(item.key)
  78. })
  79. emit('update:modelValue', keyList.join(','))
  80. emit('success', keyList.join(','))
  81. }
  82. const handleUpload = (fileData) => {
  83. const file = fileData.file
  84. const ext = file.name?.split('.')[1]
  85. const suffix = ext ? `.${ext}` : ''
  86. const fileType = props.fileType || 'other_file'
  87. getUploadPolicy({ suffix, fileType })
  88. .then(({ code, data }) => {
  89. if(code === 200) {
  90. // #ifdef APP-PLUS
  91. Object.assign(uploadData, { ...data, ...file })
  92. handleSuccess(data, file.path)
  93. // #endif
  94. // #ifdef H5
  95. uni.uploadFile({
  96. url: data.host,
  97. file: file,
  98. formData: {
  99. 'key': data.key,
  100. 'policy': data.policy,
  101. 'OSSAccessKeyId': data.ossAccessKeyId,
  102. 'success_action_status': '200',
  103. 'signature': data.signature
  104. },
  105. success: ({ statusCode }) => {
  106. if (statusCode === 200) {
  107. handleSuccess(data, fileData.url)
  108. }
  109. }
  110. })
  111. // #endif
  112. }
  113. })
  114. .catch((err) => {
  115. console.error(err)
  116. })
  117. }
  118. const handleSelectImage = ({ tempFiles }) => {
  119. tempFiles.forEach(item => {
  120. handleUpload(item)
  121. })
  122. }
  123. watchEffect(() => {
  124. if (!isUpload.value) {
  125. fileList.value = formatFiles(props.modelValue)
  126. }
  127. })
  128. </script>
  129. <script module="uploadFile" lang="renderjs">
  130. export default {
  131. methods: {
  132. tofile (data, oldValue, ownerInstance, instance) {
  133. if (data && data.path) {
  134. plus.io.resolveLocalFileSystemURL(data.path, (entry) => {
  135. entry.file((file) => {
  136. var fileReader = new plus.io.FileReader()
  137. fileReader.readAsDataURL(file)
  138. fileReader.onloadend = (evt) => {
  139. const base64Data = evt.target.result
  140. var arr = base64Data.split(',')
  141. var mime = arr[0].match(/:(.*?);/)[1]
  142. var bstr = atob(arr[1])
  143. var n = bstr.length
  144. var u8arr = new Uint8Array(n)
  145. while(n--) {
  146. u8arr[n] = bstr.charCodeAt(n)
  147. }
  148. const file = new File([u8arr], data.name, {type: mime})
  149. this.handleUpload(data, file)
  150. }
  151. })
  152. })
  153. }
  154. },
  155. handleUpload(data, file) {
  156. const formData = new FormData()
  157. formData.append('key', data.key)
  158. formData.append('policy', data.policy)
  159. formData.append('OSSAccessKeyId', data.ossAccessKeyId)
  160. formData.append('success_action_status', '200')
  161. formData.append('signature', data.signature)
  162. formData.append('file', file)
  163. // 无法使用uniapp中的上传方法,所以使用原生的上传
  164. const xhr = new XMLHttpRequest()
  165. xhr.open('POST', data.host, true)
  166. xhr.onload = (e) => {
  167. console.log(e)
  168. }
  169. xhr.send(formData)
  170. xhr.onreadystatechange = () => {
  171. if(xhr.readyState == 4 && xhr.status == 200) {
  172. console.log('上传成功!')
  173. }
  174. }
  175. }
  176. }
  177. }
  178. </script>
  179. <style lang="scss" scoped>
  180. </style>

app上传后的回调

  1. const handleUpload = (fileData) => {
  2. const file = fileData.file
  3. const ext = file.name?.split('.')[1]
  4. const suffix = ext ? `.${ext}` : ''
  5. const fileType = props.fileType || 'other_file'
  6. getUploadPolicy({ suffix, fileType })
  7. .then(({ code, data }) => {
  8. if(code === 200) {
  9. // #ifdef APP-PLUS
  10. Object.assign(uploadData, { ...data, ...file })
  11. // 强调以下这段代码其实取了巧,它有更好的实现方式是在renderjs xhr上传成功后在回调,用到了
  12. // renderjs的ownerInstance.callMethod('')实现,具体可以查文档。我为什么没用呢,是因为,
  13. // 不知道是不是用了vue3的原因,还是uniapp有bug,用不了,不触发service层数据。
  14. // ------------------------
  15. handleSuccess(data, file.path)
  16. // --------------------------
  17. // #endif
  18. }
  19. })
  20. .catch((err) => {
  21. console.error(err)
  22. })
  23. }

结束!!!!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/123945
推荐阅读
相关标签
  

闽ICP备14008679号