From 8c0d197085c2b35ba5e7094137dba11c7ddd45e0 Mon Sep 17 00:00:00 2001 From: liuxiaohang <283700113@qq.com> Date: Mon, 9 Nov 2020 13:09:06 +0800 Subject: [PATCH] feat(h5): :sparkles: add uni.chooseFile() --- lib/apis.js | 3 +- lib/modules.json | 3 +- .../helpers/protocol/media/choose-file.js | 37 ++++++++++++ .../helpers/protocol/media/choose-image.js | 4 ++ .../helpers/protocol/media/choose-video.js | 4 ++ .../h5/service/api/media/choose-file.js | 59 +++++++++++++++++++ .../h5/service/api/media/choose-image.js | 37 +++--------- .../h5/service/api/media/choose-video.js | 29 ++------- .../h5/service/api/media/create_input.js | 37 ++++++++++++ 9 files changed, 159 insertions(+), 54 deletions(-) create mode 100644 src/core/helpers/protocol/media/choose-file.js create mode 100644 src/platforms/h5/service/api/media/choose-file.js create mode 100644 src/platforms/h5/service/api/media/create_input.js diff --git a/lib/apis.js b/lib/apis.js index 4bbf77c2e..7d1669424 100644 --- a/lib/apis.js +++ b/lib/apis.js @@ -49,6 +49,7 @@ const location = [ const media = [ 'chooseImage', + 'chooseFile', 'previewImage', 'getImageInfo', 'saveImageToPhotosAlbum', @@ -170,7 +171,7 @@ const ui = [ 'showRightWindow', 'hideTopWindow', 'hideLeftWindow', - 'hideRightWindow', + 'hideRightWindow' ] const event = [ diff --git a/lib/modules.json b/lib/modules.json index 3ee506e9c..42c953af5 100644 --- a/lib/modules.json +++ b/lib/modules.json @@ -55,6 +55,7 @@ "title": "媒体", "apiList": { "uni.chooseImage": true, + "uni.chooseFile": true, "uni.previewImage": true, "uni.getImageInfo": true, "uni.saveImageToPhotosAlbum": true, @@ -216,7 +217,7 @@ "name": "ad", "title": "广告", "apiList": { - "uni.createRewardedVideoAd": true, + "uni.createRewardedVideoAd": true, "uni.createFullScreenVideoAd": true } }] diff --git a/src/core/helpers/protocol/media/choose-file.js b/src/core/helpers/protocol/media/choose-file.js new file mode 100644 index 000000000..febdc9238 --- /dev/null +++ b/src/core/helpers/protocol/media/choose-file.js @@ -0,0 +1,37 @@ +const MEDIA_TYPE = ['all', 'image', 'video'] +const SOURCE_TYPES = ['album', 'camera'] + +export const chooseFile = { + count: { + type: Number, + required: false, + default: 100, + validator (count, params) { + if (count <= 0) { + params.count = 100 + } + } + }, + sourceType: { + type: Array, + required: false, + default: SOURCE_TYPES, + validator (sourceType, params) { + sourceType = sourceType.filter(sourceType => SOURCE_TYPES.includes(sourceType)) + params.sourceType = sourceType.length ? sourceType : SOURCE_TYPES + } + }, + type: { + type: String, + required: false, + default: 'all', + validator (type, params) { + if (!MEDIA_TYPE.includes(type)) params.type = MEDIA_TYPE[0] + params.type = params.type === 'all' ? params.type = '*' : params.type + } + }, + extension: { + type: Array, + default: ['*'] + } +} diff --git a/src/core/helpers/protocol/media/choose-image.js b/src/core/helpers/protocol/media/choose-image.js index d73829c6f..3cbb6dc26 100644 --- a/src/core/helpers/protocol/media/choose-image.js +++ b/src/core/helpers/protocol/media/choose-image.js @@ -30,5 +30,9 @@ export const chooseImage = { sourceType = sourceType.filter(sourceType => SOURCE_TYPES.includes(sourceType)) params.sourceType = sourceType.length ? sourceType : SOURCE_TYPES } + }, + extension: { + type: Array, + default: ['*'] } } diff --git a/src/core/helpers/protocol/media/choose-video.js b/src/core/helpers/protocol/media/choose-video.js index 4efbf0d9a..0d5a5caa0 100644 --- a/src/core/helpers/protocol/media/choose-video.js +++ b/src/core/helpers/protocol/media/choose-video.js @@ -17,5 +17,9 @@ export const chooseVideo = { camera: { type: String, default: 'back' + }, + extension: { + type: Array, + default: ['*'] } } diff --git a/src/platforms/h5/service/api/media/choose-file.js b/src/platforms/h5/service/api/media/choose-file.js new file mode 100644 index 000000000..949b8de8c --- /dev/null +++ b/src/platforms/h5/service/api/media/choose-file.js @@ -0,0 +1,59 @@ +import { fileToUrl } from 'uni-platform/helpers/file' +import _createInput from './create_input' + +const { + invokeCallbackHandler: invoke +} = UniServiceJSBridge + +let fileInput = null + +export function chooseFile ({ + // sizeType, + count, + sourceType, + type, + extension +}, callbackId) { + // TODO handle sizeType 尝试通过 canvas 压缩 + + if (fileInput) { + document.body.removeChild(fileInput) + fileInput = null + } + + fileInput = _createInput({ + count, + sourceType, + type, + extension + }) + document.body.appendChild(fileInput) + + fileInput.addEventListener('change', function (event) { + const tempFiles = [] + const fileCount = event.target.files.length + for (let i = 0; i < fileCount; i++) { + const file = event.target.files[i] + let filePath + Object.defineProperty(file, 'path', { + get () { + filePath = filePath || fileToUrl(file) + return filePath + } + }) + if (i < count) tempFiles.push(file) + } + const res = { + errMsg: 'chooseFile:ok', + get tempFilePaths () { + return tempFiles.map(({ path }) => path) + }, + tempFiles: tempFiles + } + invoke(callbackId, res) + + // TODO 用户取消选择时,触发 fail,目前尚未找到合适的方法。 + }) + + fileInput.click() +} diff --git a/src/platforms/h5/service/api/media/choose-image.js b/src/platforms/h5/service/api/media/choose-image.js index 817b0d4da..ab7e69bb6 100644 --- a/src/platforms/h5/service/api/media/choose-image.js +++ b/src/platforms/h5/service/api/media/choose-image.js @@ -1,5 +1,5 @@ import { fileToUrl } from 'uni-platform/helpers/file' -import { updateElementStyle } from 'uni-shared' +import _createInput from './create_input' const { invokeCallbackHandler: invoke @@ -7,34 +7,11 @@ const { let imageInput = null -const _createInput = function (options) { - const inputEl = document.createElement('input') - inputEl.type = 'file' - updateElementStyle(inputEl, { - position: 'absolute', - visibility: 'hidden', - 'z-index': -999, - width: 0, - height: 0, - top: 0, - left: 0 - }) - inputEl.accept = 'image/*' - if (options.count > 1) { - inputEl.multiple = 'multiple' - } - // 经过测试,仅能限制只通过相机拍摄,不能限制只允许从相册选择。 - if (options.sourceType.length === 1 && options.sourceType[0] === 'camera') { - inputEl.capture = 'camera' - } - - return inputEl -} - export function chooseImage ({ count, // sizeType, - sourceType + sourceType, + extension }, callbackId) { // TODO handle sizeType 尝试通过 canvas 压缩 @@ -44,8 +21,10 @@ export function chooseImage ({ } imageInput = _createInput({ - count: count, - sourceType: sourceType + count, + sourceType, + extension, + type: 'image' }) document.body.appendChild(imageInput) @@ -61,7 +40,7 @@ export function chooseImage ({ return filePath } }) - tempFiles.push(file) + if (i < count) tempFiles.push(file) } const res = { errMsg: 'chooseImage:ok', diff --git a/src/platforms/h5/service/api/media/choose-video.js b/src/platforms/h5/service/api/media/choose-video.js index 30939f575..5b9c70414 100644 --- a/src/platforms/h5/service/api/media/choose-video.js +++ b/src/platforms/h5/service/api/media/choose-video.js @@ -1,5 +1,5 @@ import { fileToUrl, revokeObjectURL } from 'uni-platform/helpers/file' -import { updateElementStyle } from 'uni-shared' +import _createInput from './create_input' const { invokeCallbackHandler: invoke @@ -7,28 +7,9 @@ const { let videoInput = null -const _createInput = function (options) { - const inputEl = document.createElement('input') - inputEl.type = 'file' - updateElementStyle(inputEl, { - position: 'absolute', - visibility: 'hidden', - 'z-index': -999, - width: 0, - height: 0, - top: 0, - left: 0 - }) - inputEl.accept = 'video/*' - // 经过测试,仅能限制只通过相机拍摄,不能限制只允许从相册选择。 - if (options.sourceType.length === 1 && options.sourceType[0] === 'camera') { - inputEl.capture = 'camera' - } - return inputEl -} - export function chooseVideo ({ - sourceType + sourceType, + extension }, callbackId) { if (videoInput) { document.body.removeChild(videoInput) @@ -36,7 +17,9 @@ export function chooseVideo ({ } videoInput = _createInput({ - sourceType: sourceType + sourceType: sourceType, + extension, + type: 'video' }) document.body.appendChild(videoInput) diff --git a/src/platforms/h5/service/api/media/create_input.js b/src/platforms/h5/service/api/media/create_input.js new file mode 100644 index 000000000..d0a73eae1 --- /dev/null +++ b/src/platforms/h5/service/api/media/create_input.js @@ -0,0 +1,37 @@ +import { updateElementStyle } from 'uni-shared' + +export default function ({ count, sourceType, type, extension }) { + const inputEl = document.createElement('input') + inputEl.type = 'file' + + updateElementStyle(inputEl, { + position: 'absolute', + visibility: 'hidden', + 'z-index': -999, + width: 0, + height: 0, + top: 0, + left: 0 + }) + + inputEl.accept = extension.map(item => { + if (type !== '*') { + // 剔除.拼接在type后 + return `${type}/${item.replace('.', '')}` + } else { + // 在后缀前方加上. + return item.indexOf('.') === 0 ? item : `.${item}` + } + }).join(',') + + if (count > 1) { + inputEl.multiple = 'multiple' + } + + // 经过测试,仅能限制只通过相机拍摄,不能限制只允许从相册选择。 + if (sourceType.length === 1 && sourceType[0] === 'camera') { + inputEl.capture = 'camera' + } + + return inputEl +} -- GitLab