upload-file.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (C) 2020 Tencent Cloud.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import UUID from 'uuid';
  17. import { getMediaType } from './utils';
  18. /**
  19. * 上传文件到腾讯云COS(需要调用云函数签名,请先配置好云函数)
  20. * @async
  21. * @param {string|File} file - 需要上传的文件,小程序环境选择的filePath或H5环境选择的File对象
  22. * @param {string?} key - 存储在COS上的文件名称,如果不传,则会生成uuid代替
  23. * @param {function?} onProgressUpdate - 上传进度回调,回调参数详见uni.uploadFile API
  24. * @return {Promise<string>} 返回成功上传到COS上的文件名称
  25. */
  26. export default async function uploadFile(file, key, onProgressUpdate) {
  27. if (!file) {
  28. throw new Error('file不能为空');
  29. }
  30. // 获取签名信息
  31. const { result } = await uniCloud.callFunction({
  32. name: 'tencentcloud-plugin',
  33. data: {
  34. module: 'COS',
  35. action: 'signPostObjectAPI',
  36. },
  37. });
  38. const signData = result;
  39. console.log('key:'+key)
  40. console.log(signData)
  41. return new Promise((resolve, reject) => {
  42. let filePath = undefined;
  43. let fileExt;
  44. if (typeof file === 'string') {
  45. filePath = file;
  46. file = undefined;
  47. fileExt = filePath.split('?')[0].split('.').pop();
  48. } else {
  49. fileExt = file.name.split('.').pop();
  50. }
  51. // 支付宝小程序上传文件API必传fileType
  52. // 通过支付宝小程序环境下选择文件的时候,通过返回的filePath取得的扩展名可能是image/video/audio
  53. let fileType = undefined;
  54. // ifdef MP-ALIPAY
  55. if (fileExt === 'image') {
  56. fileExt = 'jpg';
  57. } else if (fileExt === 'video') {
  58. fileExt = 'mp4';
  59. } else if (fileExt === 'audio') {
  60. fileExt = 'mp3';
  61. }
  62. fileType = getMediaType(fileExt);
  63. // endif
  64. if (!key) {
  65. key = `${UUID.v1()}.${fileExt}`;
  66. }
  67. console.log(key)
  68. console.log('file',file)
  69. console.log('filePath',filePath)
  70. console.log('fileType',fileType)
  71. console.log({
  72. key,
  73. 'q-sign-algorithm': signData.signAlgorithm,
  74. 'q-ak': signData.ak,
  75. 'q-key-time': signData.keyTime,
  76. 'q-signature': signData.signature,
  77. 'policy': signData.policy
  78. })
  79. const uploadTask = uni.uploadFile({
  80. url: signData.host,
  81. file,
  82. filePath,
  83. fileType,
  84. name: 'file',
  85. formData: {
  86. key,
  87. 'q-sign-algorithm': signData.signAlgorithm,
  88. 'q-ak': signData.ak,
  89. 'q-key-time': signData.keyTime,
  90. 'q-signature': signData.signature,
  91. 'policy': signData.policy
  92. },
  93. success(response) {
  94. console.log(response)
  95. if (response.statusCode !== 204) {
  96. reject(new Error('文件上传失败'));
  97. } else {
  98. resolve(key);
  99. }
  100. },
  101. complete(r){
  102. console.log('回调执行成功')
  103. },
  104. fail(error) {
  105. // 支付宝小程序环境下会将返回的204状态码识别为异常而触发fail回调,实际上是上传成功了的
  106. console.log(error)
  107. if (error.statusCode === 204) {
  108. resolve(key);
  109. } else {
  110. reject(error);
  111. }
  112. }
  113. });
  114. onProgressUpdate && uploadTask.onProgressUpdate(onProgressUpdate);
  115. });
  116. };