choose-and-upload-file.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. 'use strict';
  2. // #ifdef APP
  3. import { usePermissionStore } from "@/store/modules/permission";
  4. // #endif
  5. const ERR_MSG_OK = 'chooseAndUploadFile:ok';
  6. const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
  7. function chooseImage(opts) {
  8. const {
  9. count,
  10. sizeType = ['original', 'compressed'],
  11. sourceType,
  12. extension
  13. } = opts
  14. return new Promise((resolve, reject) => {
  15. // 微信由于旧接口不再维护,针对微信小程序平台改用chooseMedia接口
  16. // #ifdef MP-WEIXIN
  17. uni.chooseMedia({
  18. count,
  19. sizeType,
  20. sourceType,
  21. mediaType: ['image'],
  22. extension,
  23. success(res) {
  24. res.tempFiles.forEach(item => {
  25. item.path = item.tempFilePath;
  26. })
  27. resolve(normalizeChooseAndUploadFileRes(res, 'image'));
  28. },
  29. fail(res) {
  30. reject({
  31. errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
  32. });
  33. },
  34. })
  35. // #endif
  36. // #ifdef APP
  37. const { requestImagePermissions } = usePermissionStore()
  38. requestImagePermissions().then(() => {
  39. uni.chooseImage({
  40. count,
  41. sizeType,
  42. sourceType,
  43. extension,
  44. success(res) {
  45. resolve(normalizeChooseAndUploadFileRes(res, 'image'));
  46. },
  47. fail(res) {
  48. reject({
  49. errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
  50. });
  51. },
  52. });
  53. })
  54. // #endif
  55. // #ifndef MP-WEIXIN, APP
  56. uni.chooseImage({
  57. count,
  58. sizeType,
  59. sourceType,
  60. extension,
  61. success(res) {
  62. resolve(normalizeChooseAndUploadFileRes(res, 'image'));
  63. },
  64. fail(res) {
  65. reject({
  66. errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
  67. });
  68. },
  69. });
  70. // #endif
  71. });
  72. }
  73. function chooseVideo(opts) {
  74. const {
  75. count,
  76. camera,
  77. compressed,
  78. maxDuration,
  79. sourceType,
  80. extension
  81. } = opts;
  82. return new Promise((resolve, reject) => {
  83. // 微信由于旧接口不再维护,针对微信小程序平台改用chooseMedia接口
  84. // #ifdef MP-WEIXIN
  85. uni.chooseMedia({
  86. count,
  87. compressed,
  88. maxDuration,
  89. sourceType,
  90. extension,
  91. mediaType: ['video'],
  92. success(res) {
  93. const {
  94. tempFiles,
  95. } = res;
  96. resolve(normalizeChooseAndUploadFileRes({
  97. errMsg: 'chooseVideo:ok',
  98. tempFiles: tempFiles.map(item => {
  99. return {
  100. name: item.name || '',
  101. path: item.tempFilePath,
  102. thumbTempFilePath: item.thumbTempFilePath,
  103. size:item.size,
  104. type: (res.tempFile && res.tempFile.type) || '',
  105. width:item.width,
  106. height:item.height,
  107. duration:item.duration,
  108. fileType: 'video',
  109. cloudPath: '',
  110. }
  111. }),
  112. }, 'video'));
  113. },
  114. fail(res) {
  115. reject({
  116. errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
  117. });
  118. },
  119. })
  120. // #endif
  121. // #ifndef MP-WEIXIN
  122. uni.chooseVideo({
  123. camera,
  124. compressed,
  125. maxDuration,
  126. sourceType,
  127. extension,
  128. success(res) {
  129. const {
  130. tempFilePath,
  131. duration,
  132. size,
  133. height,
  134. width
  135. } = res;
  136. resolve(normalizeChooseAndUploadFileRes({
  137. errMsg: 'chooseVideo:ok',
  138. tempFilePaths: [tempFilePath],
  139. tempFiles: [{
  140. name: (res.tempFile && res.tempFile.name) || '',
  141. path: tempFilePath,
  142. size,
  143. type: (res.tempFile && res.tempFile.type) || '',
  144. width,
  145. height,
  146. duration,
  147. fileType: 'video',
  148. cloudPath: '',
  149. }, ],
  150. }, 'video'));
  151. },
  152. fail(res) {
  153. reject({
  154. errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
  155. });
  156. },
  157. });
  158. // #endif
  159. });
  160. }
  161. function chooseAll(opts) {
  162. const {
  163. count,
  164. extension
  165. } = opts;
  166. return new Promise((resolve, reject) => {
  167. let chooseFile = uni.chooseFile;
  168. if (typeof wx !== 'undefined' &&
  169. typeof wx.chooseMessageFile === 'function') {
  170. chooseFile = wx.chooseMessageFile;
  171. }
  172. if (typeof chooseFile !== 'function') {
  173. return reject({
  174. errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
  175. });
  176. }
  177. chooseFile({
  178. type: 'all',
  179. count,
  180. extension,
  181. success(res) {
  182. resolve(normalizeChooseAndUploadFileRes(res));
  183. },
  184. fail(res) {
  185. reject({
  186. errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
  187. });
  188. },
  189. });
  190. });
  191. }
  192. function normalizeChooseAndUploadFileRes(res, fileType) {
  193. res.tempFiles.forEach((item, index) => {
  194. if (!item.name) {
  195. item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
  196. }
  197. if (fileType) {
  198. item.fileType = fileType;
  199. }
  200. item.cloudPath =
  201. Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
  202. });
  203. if (!res.tempFilePaths) {
  204. res.tempFilePaths = res.tempFiles.map((file) => file.path);
  205. }
  206. return res;
  207. }
  208. function uploadCloudFiles(files, max = 5, onUploadProgress) {
  209. files = JSON.parse(JSON.stringify(files))
  210. const len = files.length
  211. let count = 0
  212. let self = this
  213. return new Promise(resolve => {
  214. while (count < max) {
  215. next()
  216. }
  217. function next() {
  218. let cur = count++
  219. if (cur >= len) {
  220. !files.find(item => !item.url && !item.errMsg) && resolve(files)
  221. return
  222. }
  223. const fileItem = files[cur]
  224. const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
  225. fileItem.url = ''
  226. delete fileItem.errMsg
  227. uniCloud
  228. .uploadFile({
  229. filePath: fileItem.path,
  230. cloudPath: fileItem.cloudPath,
  231. fileType: fileItem.fileType,
  232. onUploadProgress: res => {
  233. res.index = index
  234. onUploadProgress && onUploadProgress(res)
  235. }
  236. })
  237. .then(res => {
  238. fileItem.url = res.fileID
  239. fileItem.index = index
  240. if (cur < len) {
  241. next()
  242. }
  243. })
  244. .catch(res => {
  245. fileItem.errMsg = res.errMsg || res.message
  246. fileItem.index = index
  247. if (cur < len) {
  248. next()
  249. }
  250. })
  251. }
  252. })
  253. }
  254. function uploadFiles(choosePromise, {
  255. onChooseFile,
  256. onUploadProgress
  257. }) {
  258. return choosePromise
  259. .then((res) => {
  260. if (onChooseFile) {
  261. const customChooseRes = onChooseFile(res);
  262. if (typeof customChooseRes !== 'undefined') {
  263. return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
  264. res : chooseRes);
  265. }
  266. }
  267. return res;
  268. })
  269. .then((res) => {
  270. if (res === false) {
  271. return {
  272. errMsg: ERR_MSG_OK,
  273. tempFilePaths: [],
  274. tempFiles: [],
  275. };
  276. }
  277. return res
  278. })
  279. }
  280. function chooseAndUploadFile(opts = {
  281. type: 'all'
  282. }) {
  283. if (opts.type === 'image') {
  284. return uploadFiles(chooseImage(opts), opts);
  285. } else if (opts.type === 'video') {
  286. return uploadFiles(chooseVideo(opts), opts);
  287. }
  288. return uploadFiles(chooseAll(opts), opts);
  289. }
  290. export {
  291. chooseAndUploadFile,
  292. uploadCloudFiles
  293. };