feat: send file message

This commit is contained in:
zerosoul
2022-03-28 20:45:53 +08:00
parent d07b0e9e91
commit 774bf2c335
12 changed files with 396 additions and 7 deletions
+124
View File
@@ -0,0 +1,124 @@
import { useState, useRef } from "react";
// import { ContentTypes } from "../../app/config";
// import { sliceFile } from "../utils";
import { FILE_SLICE_SIZE } from "../../app/config";
import {
usePrepareUploadFileMutation,
useUploadFileMutation,
} from "../../app/services/message";
import { useSendMsgMutation } from "../../app/services/contact";
import { useSendChannelMsgMutation } from "../../app/services/channel";
export default function useUploadImageMessage({
context = "user",
from = null,
to = null,
}) {
// const slicedRef = useRef(false);
const [uploadingFile, setUploadingFile] = useState(false);
const sliceUploadedCountRef = useRef(0);
const totalSliceCountRef = useRef(1);
// const [uploadedSliceCount, setUploadedSliceCount] = useState(0)
const [
prepareUploadFile,
{ isLoading: isPreparing, isSuccess: isPrepared },
] = usePrepareUploadFileMutation();
const [
uploadFile,
{ isLoading: isUploading, isSuccess: isUploaded, isError: uploadFileError },
] = useUploadFileMutation();
const [
sendChannelMsg,
{
isLoading: channelSending,
isSuccess: channelSuccess,
isError: channelError,
},
] = useSendChannelMsgMutation();
const [
sendUserMsg,
{ isLoading: userSending, isSuccess: userSuccess, isError: userError },
] = useSendMsgMutation();
const sendFn = context == "user" ? sendUserMsg : sendChannelMsg;
const uploadChunk = async (data) => {
const { file_id, chunk, is_last } = data;
const formData = new FormData();
formData.append("file_id", file_id);
formData.append("chunk_data", chunk);
formData.append("chunk_is_last", is_last);
return uploadFile(formData);
};
const sendFileMessage = async (file) => {
if (!file) return;
const { name, type: file_type, size: file_size } = file;
// 拿file id
const { data: file_id } = await prepareUploadFile();
console.log("file id", file_id);
let uploadResult = null;
totalSliceCountRef.current = 1;
setUploadingFile(true);
// 2MB
if (file_size <= 1000 * 1000 * 2) {
// 一次性上传文件
uploadResult = await uploadChunk({ file_id, chunk: file, is_last: true });
sliceUploadedCountRef.current = 1;
} else {
// 分片上传文件
totalSliceCountRef.current = Math.ceil(file_size / FILE_SLICE_SIZE);
const totalSliceCount = totalSliceCountRef.current;
const _arr = new Array(totalSliceCount);
// const chunk=file.slice(block_size * index, block_size * (index + 1));
for await (const [idx] of _arr.entries()) {
try {
const chunk = file.slice(
FILE_SLICE_SIZE * idx,
FILE_SLICE_SIZE * (idx + 1),
file_type
);
if (idx == _arr.length - 1) {
uploadResult = await uploadChunk({ file_id, chunk, is_last: true });
} else {
await uploadChunk({ file_id, chunk, is_last: false });
}
sliceUploadedCountRef.current = sliceUploadedCountRef.current + 1;
} catch (error) {
return;
}
}
console.log("wtfff", uploadResult);
}
setUploadingFile(false);
const {
data: { path, size, hash },
} = uploadResult;
const content = JSON.stringify({
name,
size,
hash,
path,
});
console.log("upload content", content);
await sendFn({
id: to,
content,
type: "file",
properties: { file_type },
from_uid: from,
});
};
const isSending =
userSending || channelSending || isPreparing || uploadingFile;
return {
progress: isSending
? sliceUploadedCountRef.current / totalSliceCountRef.current
: 1,
sendFileMessage,
isError: channelError || userError || uploadFileError,
isSending,
isSuccess: (channelSuccess || userSuccess) && isPrepared,
};
}
+39
View File
@@ -0,0 +1,39 @@
// import second from 'first'
import { useSendChannelMsgMutation } from "../../app/services/channel";
import { useSendMsgMutation } from "../../app/services/contact";
export default function useSendImageMessage({
context = "user",
from = null,
to = null,
}) {
const [
sendChannelMsg,
{
isLoading: channelSending,
isSuccess: channelSuccess,
isError: channelError,
},
] = useSendChannelMsgMutation();
const [
sendUserMsg,
{ isLoading: userSending, isSuccess: userSuccess, isError: userError },
] = useSendMsgMutation();
const uploadFn = context == "user" ? sendUserMsg : sendChannelMsg;
const sendImageMessage = (file) => {
if (!file) return;
const { name, size, type } = file;
uploadFn({
id: to,
content: file,
properties: { name, size, type, local_id: new Date().getTime() },
type: "image",
from_uid: from,
});
};
return {
sendImageMessage,
isError: channelError || userError,
isSending: userSending || channelSending,
isSuccess: channelSuccess || userSuccess,
};
}