choose-and-upload-file.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. 'use strict';
  2. const ERR_MSG_OK = 'chooseAndUploadFile:ok';
  3. const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
  4. function chooseImage(opts) {
  5. const {
  6. count,
  7. sizeType = ['original', 'compressed'],
  8. sourceType,
  9. extension
  10. } = opts
  11. return new Promise((resolve, reject) => {
  12. uni.chooseImage({
  13. count,
  14. sizeType,
  15. sourceType,
  16. extension,
  17. success(res) {
  18. resolve(normalizeChooseAndUploadFileRes(res, 'image'));
  19. },
  20. fail(res) {
  21. reject({
  22. errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
  23. });
  24. },
  25. });
  26. });
  27. }
  28. function chooseVideo(opts) {
  29. const {
  30. camera,
  31. compressed,
  32. maxDuration,
  33. sourceType,
  34. extension
  35. } = opts;
  36. return new Promise((resolve, reject) => {
  37. uni.chooseVideo({
  38. camera,
  39. compressed,
  40. maxDuration,
  41. sourceType,
  42. extension,
  43. success(res) {
  44. const {
  45. tempFilePath,
  46. duration,
  47. size,
  48. height,
  49. width
  50. } = res;
  51. resolve(normalizeChooseAndUploadFileRes({
  52. errMsg: 'chooseVideo:ok',
  53. tempFilePaths: [tempFilePath],
  54. tempFiles: [
  55. {
  56. name: (res.tempFile && res.tempFile.name) || '',
  57. path: tempFilePath,
  58. size,
  59. type: (res.tempFile && res.tempFile.type) || '',
  60. width,
  61. height,
  62. duration,
  63. fileType: 'video',
  64. cloudPath: '',
  65. }, ],
  66. }, 'video'));
  67. },
  68. fail(res) {
  69. reject({
  70. errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
  71. });
  72. },
  73. });
  74. });
  75. }
  76. function chooseAll(opts) {
  77. const {
  78. count,
  79. extension
  80. } = opts;
  81. return new Promise((resolve, reject) => {
  82. let chooseFile = uni.chooseFile;
  83. if (typeof wx !== 'undefined' &&
  84. typeof wx.chooseMessageFile === 'function') {
  85. chooseFile = wx.chooseMessageFile;
  86. }
  87. if (typeof chooseFile !== 'function') {
  88. return reject({
  89. errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
  90. });
  91. }
  92. chooseFile({
  93. type: 'all',
  94. count,
  95. extension,
  96. success(res) {
  97. resolve(normalizeChooseAndUploadFileRes(res));
  98. },
  99. fail(res) {
  100. reject({
  101. errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
  102. });
  103. },
  104. });
  105. });
  106. }
  107. function normalizeChooseAndUploadFileRes(res, fileType) {
  108. res.tempFiles.forEach((item, index) => {
  109. if (!item.name) {
  110. item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
  111. }
  112. if (fileType) {
  113. item.fileType = fileType;
  114. }
  115. item.cloudPath =
  116. Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
  117. });
  118. if (!res.tempFilePaths) {
  119. res.tempFilePaths = res.tempFiles.map((file) => file.path);
  120. }
  121. return res;
  122. }
  123. function uploadCloudFiles(files, max = 5, onUploadProgress) {
  124. files = JSON.parse(JSON.stringify(files))
  125. const len = files.length
  126. let count = 0
  127. let self = this
  128. return new Promise(resolve => {
  129. while (count < max) {
  130. next()
  131. }
  132. function next() {
  133. let cur = count++
  134. if (cur >= len) {
  135. !files.find(item => !item.url && !item.errMsg) && resolve(files)
  136. return
  137. }
  138. const fileItem = files[cur]
  139. const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
  140. fileItem.url = ''
  141. delete fileItem.errMsg
  142. uniCloud
  143. .uploadFile({
  144. filePath: fileItem.path,
  145. cloudPath: fileItem.cloudPath,
  146. fileType: fileItem.fileType,
  147. onUploadProgress: res => {
  148. res.index = index
  149. onUploadProgress && onUploadProgress(res)
  150. }
  151. })
  152. .then(res => {
  153. fileItem.url = res.fileID
  154. fileItem.index = index
  155. if (cur < len) {
  156. next()
  157. }
  158. })
  159. .catch(res => {
  160. fileItem.errMsg = res.errMsg || res.message
  161. fileItem.index = index
  162. if (cur < len) {
  163. next()
  164. }
  165. })
  166. }
  167. })
  168. }
  169. function uploadFiles(choosePromise, {
  170. onChooseFile,
  171. onUploadProgress
  172. }) {
  173. return choosePromise
  174. .then((res) => {
  175. if (onChooseFile) {
  176. const customChooseRes = onChooseFile(res);
  177. if (typeof customChooseRes !== 'undefined') {
  178. return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
  179. res : chooseRes);
  180. }
  181. }
  182. return res;
  183. })
  184. .then((res) => {
  185. if (res === false) {
  186. return {
  187. errMsg: ERR_MSG_OK,
  188. tempFilePaths: [],
  189. tempFiles: [],
  190. };
  191. }
  192. return res
  193. })
  194. }
  195. function chooseAndUploadFile(opts = {
  196. type: 'all'
  197. }) {
  198. if (opts.type === 'image') {
  199. return uploadFiles(chooseImage(opts), opts);
  200. }
  201. else if (opts.type === 'video') {
  202. return uploadFiles(chooseVideo(opts), opts);
  203. }
  204. return uploadFiles(chooseAll(opts), opts);
  205. }
  206. export {
  207. chooseAndUploadFile,
  208. uploadCloudFiles
  209. };