待测试
This commit is contained in:
@@ -8,6 +8,7 @@ const createUploadError = (message, code) => {
|
||||
};
|
||||
|
||||
export const isImagePickCancelled = (error) => error?.code === "IMAGE_PICK_CANCELLED";
|
||||
export const isVideoPickCancelled = (error) => error?.code === "VIDEO_PICK_CANCELLED";
|
||||
|
||||
const createUploadId = () => {
|
||||
if (typeof globalThis.crypto?.randomUUID === "function") return globalThis.crypto.randomUUID();
|
||||
@@ -73,7 +74,66 @@ const pickBrowserImage = () => new Promise((resolve, reject) => {
|
||||
input.click();
|
||||
});
|
||||
|
||||
const readNativeImage = (filePath) => new Promise((resolve, reject) => {
|
||||
const pickNativeVideo = () => new Promise((resolve, reject) => {
|
||||
if (!globalThis.plus?.gallery?.pick) {
|
||||
reject(createUploadError("当前运行环境不支持从相册选择视频", "VIDEO_PICK_UNAVAILABLE"));
|
||||
return;
|
||||
}
|
||||
globalThis.plus.gallery.pick(
|
||||
(filePath) => resolve(filePath),
|
||||
() => reject(createUploadError("已取消选择视频", "VIDEO_PICK_CANCELLED")),
|
||||
{ filter: "video", multiple: false },
|
||||
);
|
||||
});
|
||||
|
||||
const pickBrowserVideo = () => new Promise((resolve, reject) => {
|
||||
if (typeof globalThis.document?.createElement !== "function" || typeof globalThis.FileReader !== "function") {
|
||||
reject(createUploadError("当前运行环境不支持选择视频", "VIDEO_PICK_UNAVAILABLE"));
|
||||
return;
|
||||
}
|
||||
const input = globalThis.document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = "video/*";
|
||||
input.style.display = "none";
|
||||
const cleanup = () => input.remove();
|
||||
input.addEventListener("cancel", () => {
|
||||
cleanup();
|
||||
reject(createUploadError("已取消选择视频", "VIDEO_PICK_CANCELLED"));
|
||||
}, { once: true });
|
||||
input.addEventListener("change", () => {
|
||||
const browserFile = input.files?.[0];
|
||||
if (!browserFile) {
|
||||
cleanup();
|
||||
reject(createUploadError("已取消选择视频", "VIDEO_PICK_CANCELLED"));
|
||||
return;
|
||||
}
|
||||
const reader = new globalThis.FileReader();
|
||||
reader.onload = () => {
|
||||
const data = reader.result;
|
||||
cleanup();
|
||||
if (!(data instanceof ArrayBuffer)) {
|
||||
reject(createUploadError("读取视频数据失败", "VIDEO_READ_INVALID"));
|
||||
return;
|
||||
}
|
||||
resolve({
|
||||
browserFile,
|
||||
fileName: browserFile.name || "video",
|
||||
size: browserFile.size,
|
||||
contentType: browserFile.type || "video/*",
|
||||
data,
|
||||
});
|
||||
};
|
||||
reader.onerror = () => {
|
||||
cleanup();
|
||||
reject(createUploadError("读取视频数据失败", "VIDEO_READ_FAILED"));
|
||||
};
|
||||
reader.readAsArrayBuffer(browserFile);
|
||||
}, { once: true });
|
||||
globalThis.document.body?.append(input);
|
||||
input.click();
|
||||
});
|
||||
|
||||
const readNativeFile = (filePath) => new Promise((resolve, reject) => {
|
||||
if (!globalThis.plus?.io?.resolveLocalFileSystemURL || !globalThis.plus?.io?.FileReader) {
|
||||
reject(createUploadError("当前运行环境不支持读取图片", "IMAGE_READ_UNAVAILABLE"));
|
||||
return;
|
||||
@@ -137,7 +197,7 @@ const toUploadReceipt = ({ ossId, url = "", thumbnailUrl = "", fileName = "" })
|
||||
|
||||
export const pickAndUploadImage = async ({ requestController = null } = {}) => {
|
||||
const file = globalThis.plus?.gallery?.pick
|
||||
? await readNativeImage(await pickNativeImage())
|
||||
? await readNativeFile(await pickNativeImage())
|
||||
: await pickBrowserImage();
|
||||
if (!Number.isSafeInteger(file.size) || file.size <= 0) {
|
||||
throw createUploadError("所选图片大小无效", "IMAGE_SIZE_INVALID");
|
||||
@@ -173,3 +233,46 @@ export const pickAndUploadImage = async ({ requestController = null } = {}) => {
|
||||
}, { requestController });
|
||||
return toUploadReceipt(completed);
|
||||
};
|
||||
|
||||
export const pickAndUploadVideo = async ({ requestController = null } = {}) => {
|
||||
const file = globalThis.plus?.gallery?.pick
|
||||
? await readNativeFile(await pickNativeVideo())
|
||||
: await pickBrowserVideo();
|
||||
const fileName = String(file.fileName || "");
|
||||
if (!String(file.contentType || "").startsWith("video/") && !/\.(mp4|mov|m4v|webm|avi|mkv)$/i.test(fileName)) {
|
||||
throw createUploadError("请选择视频文件", "VIDEO_TYPE_INVALID");
|
||||
}
|
||||
if (!Number.isSafeInteger(file.size) || file.size <= 0) {
|
||||
throw createUploadError("所选视频大小无效", "VIDEO_SIZE_INVALID");
|
||||
}
|
||||
const fileMd5 = calcMD5Bytes(file.data);
|
||||
const initPayload = {
|
||||
uploadId: createUploadId(),
|
||||
fileName,
|
||||
fileMd5,
|
||||
totalSize: file.size,
|
||||
totalChunks: 1,
|
||||
chunkSize: file.size,
|
||||
contentType: file.contentType || "video/*",
|
||||
};
|
||||
const initialized = await appApi.initializeResumableUpload(initPayload, { requestController });
|
||||
if (initialized.instant) return toUploadReceipt(initialized);
|
||||
const chunkPayload = {
|
||||
uploadId: initialized.uploadId,
|
||||
chunkIndex: 0,
|
||||
chunkMd5: fileMd5,
|
||||
};
|
||||
if (file.browserFile) {
|
||||
await appApi.uploadBrowserResumableChunk(chunkPayload, file.browserFile, { requestController });
|
||||
} else {
|
||||
await appApi.uploadResumableChunk({ ...chunkPayload, filePath: file.filePath }, { requestController });
|
||||
}
|
||||
const completed = await appApi.completeResumableUpload({
|
||||
uploadId: initialized.uploadId,
|
||||
fileName,
|
||||
fileMd5,
|
||||
totalSize: file.size,
|
||||
totalChunks: 1,
|
||||
}, { requestController });
|
||||
return toUploadReceipt(completed);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user