-
Notifications
You must be signed in to change notification settings - Fork 100
feat(fs): slice upload #187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
9291056
88ad014
a4ece2d
757a74f
0e484dd
39752d1
1756627
91d83a0
5b2f8fb
ae51cfa
8ab5c5d
5579321
3766f0b
b71edb9
54dab7a
238896f
9e2272a
6b77cb0
7b7e6b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,253 @@ | ||||||||||
import { password } from "~/store" | ||||||||||
import { EmptyResp } from "~/types" | ||||||||||
import { r, pathDir, log } from "~/utils" | ||||||||||
import { SetUpload, Upload } from "./types" | ||||||||||
import pLimit from "p-limit" | ||||||||||
import { | ||||||||||
calculateHash, | ||||||||||
calculateSliceHash, | ||||||||||
fsUploadInfo, | ||||||||||
fsPreup, | ||||||||||
FsSliceupComplete, | ||||||||||
HashType, | ||||||||||
} from "./util" | ||||||||||
import createMutex from "~/utils/mutex" | ||||||||||
|
||||||||||
const progressMutex = createMutex() | ||||||||||
|
||||||||||
export const sliceupload = async ( | ||||||||||
uploadPath: string, | ||||||||||
file: File, | ||||||||||
setUpload: SetUpload, | ||||||||||
overwrite = false, | ||||||||||
asTask = false, | ||||||||||
): Promise<Error | undefined> => { | ||||||||||
let hashtype: string = HashType.Md5 | ||||||||||
let slicehash: string[] = [] | ||||||||||
let sliceupstatus: Uint8Array | ||||||||||
let ht: string[] = [] | ||||||||||
|
||||||||||
const dir = pathDir(uploadPath) | ||||||||||
|
||||||||||
//获取上传需要的信息 | ||||||||||
const resp = await fsUploadInfo(dir) | ||||||||||
if (resp.code != 200) { | ||||||||||
return new Error(resp.message) | ||||||||||
} | ||||||||||
|
||||||||||
// hash计算 | ||||||||||
if (resp.data.hash_md5_need) { | ||||||||||
ht.push(HashType.Md5) | ||||||||||
hashtype = HashType.Md5 | ||||||||||
} | ||||||||||
if (resp.data.hash_sha1_need) { | ||||||||||
ht.push(HashType.Sha1) | ||||||||||
hashtype = HashType.Sha1 | ||||||||||
} | ||||||||||
if (resp.data.hash_md5_256kb_need) { | ||||||||||
ht.push(HashType.Md5256kb) | ||||||||||
} | ||||||||||
const hash = await calculateHash(file, ht) | ||||||||||
// 预上传 | ||||||||||
const resp1 = await fsPreup( | ||||||||||
dir, | ||||||||||
file.name, | ||||||||||
file.size, | ||||||||||
hash, | ||||||||||
overwrite, | ||||||||||
asTask, | ||||||||||
) | ||||||||||
if (resp1.code != 200) { | ||||||||||
return new Error(resp1.message) | ||||||||||
} | ||||||||||
if (resp1.data.reuse) { | ||||||||||
setUpload("progress", "100") | ||||||||||
setUpload("status", "success") | ||||||||||
setUpload("speed", "0") | ||||||||||
return | ||||||||||
} | ||||||||||
//计算分片hash | ||||||||||
if (resp.data.slice_hash_need) { | ||||||||||
slicehash = await calculateSliceHash(file, resp1.data.slice_size, hashtype) | ||||||||||
} | ||||||||||
// 分片上传状态 | ||||||||||
sliceupstatus = base64ToUint8Array(resp1.data.slice_upload_status) | ||||||||||
|
||||||||||
// 进度和速度统计 | ||||||||||
let uploadedBytes = 0 | ||||||||||
let lastTimestamp = Date.now() | ||||||||||
let lastUploadedBytes = 0 | ||||||||||
const totalSize = file.size | ||||||||||
let completeFlag = false | ||||||||||
|
||||||||||
// 上传分片的核心函数,带进度和速度统计 | ||||||||||
const uploadChunk = async ( | ||||||||||
chunk: Blob, | ||||||||||
idx: number, | ||||||||||
slice_hash: string, | ||||||||||
upload_id: number, | ||||||||||
) => { | ||||||||||
const formData = new FormData() | ||||||||||
formData.append("upload_id", upload_id.toString()) | ||||||||||
formData.append("slice_hash", slice_hash) | ||||||||||
formData.append("slice_num", idx.toString()) | ||||||||||
formData.append("slice", chunk) | ||||||||||
|
||||||||||
let oldTimestamp = Date.now() | ||||||||||
let oldLoaded = 0 | ||||||||||
|
||||||||||
const resp: EmptyResp = await r.post("/fs/slice_upload", formData, { | ||||||||||
headers: { | ||||||||||
"File-Path": encodeURIComponent(dir), | ||||||||||
"Content-Type": "multipart/form-data", | ||||||||||
Password: password(), | ||||||||||
}, | ||||||||||
onUploadProgress: async (progressEvent) => { | ||||||||||
log() | ||||||||||
if (!progressEvent.lengthComputable) { | ||||||||||
return | ||||||||||
} | ||||||||||
//获取锁 | ||||||||||
const release = await progressMutex.acquire() | ||||||||||
try { | ||||||||||
const sliceuploaded = progressEvent.loaded - oldLoaded | ||||||||||
log("progress event trigger", idx, sliceuploaded, Date.now()) | ||||||||||
uploadedBytes += sliceuploaded | ||||||||||
oldLoaded = progressEvent.loaded | ||||||||||
} finally { | ||||||||||
progressMutex.release() | ||||||||||
|
oldLoaded = progressEvent.loaded | |
} finally { | |
progressMutex.release() | |
release() |
Copilot uses AI. Check for mistakes.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bitwise OR operation '| 0' for rounding is unclear. Use 'Math.floor()' instead for better readability and explicit intent.
const speed = intervalLoaded / ((Date.now() - lastTimestamp) / 1000) | |
const complete = Math.min(100, ((uploadedBytes / file.size) * 100) | 0) | |
const complete = Math.min(100, Math.floor((uploadedBytes / file.size) * 100)) |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log() function is called without any arguments on line 106, which may not provide useful debugging information. Consider adding meaningful parameters or removing if not needed.
Copilot uses AI. Check for mistakes.