我最近才在處理AWS SDK,因此如果我的方法完全是胡說八道,請原諒。
我想將一個簡單的媒體檔案上傳到我的 S3。我正在關注本教程,到目前為止,我可以毫無問題地上傳檔案。為了便于使用,進度條將是一個不錯的附加功能,因此我正在研究如何實作這一點。我很快發現當前的 AWS SDK v3不再支持httpUploadProgress,但我們應該使用它@aws-sdk/lib-storage。使用這個庫,我仍然可以將檔案上傳到 S3,但我無法讓進度跟蹤器作業!我認為這與我沒有完全理解如何async在 React 組件中處理有關。
所以這是我的縮小組件示例(我在這里使用 Chakra UI)
const TestAWS: React.FC = () => {
const inputRef = useRef<HTMLInputElement | null>(null);
const [progr, setProgr] = useState<number>();
const region = "eu-west-1";
const bucketname = "upload-test";
const handleClick = async () => {
inputRef.current?.click();
};
const handleChange = (e: any) => {
console.log('Start file upload');
const file = e.target.files[0];
const target = {
Bucket: bucketname,
Key: `jobs/${file.name}`,
Body: file,
};
const s3 = new S3Client({
region: region,
credentials: fromCognitoIdentityPool({
client: new CognitoIdentityClient({ region: region }),
identityPoolId: "---MY ID---",
}),
});
const upload = new Upload({
client: s3,
params: target,
});
const t = upload.on("httpUploadProgress", progress => {
console.log("Progress", progress);
if (progress.loaded && progress.total) {
console.log("loaded/total", progress.loaded, progress.total);
setProgr(Math.round((progress.loaded / progress.total) * 100)); // I was expecting this line to be sufficient for updating my component
}
});
await upload.done().then(r => console.log(r));
};
console.log('Progress', progr);
return (
<InputGroup onClick={handleClick}>
<input ref={inputRef} type={"file"} multiple={false} hidden accept='video/*' onChange={e => handleChange(e)} />
<Flex layerStyle='uploadField'>
<Center w='100%'>
<VStack>
<PlusIcon />
<Text>Choose Video File</Text>
</VStack>
</Center>
</Flex>
{progr && <Progress value={progr} />}
</InputGroup>
);
};
export default TestAWS;
所以基本上我看到事件被觸發(開始檔案上傳)。然后需要一段時間,我Progress, 100在控制臺中看到了 Promise 結果和。這對我來說意味著狀態變數會更新(至少一次)但組件不會重新渲染?
我在這里做錯了什么?任何幫助表示贊賞!
uj5u.com熱心網友回復:
好的,我找到了解決方案。狀態變數上的回呼作業正常并完成它應該做的事情。但是Upload物件的配置是關閉的。在深入研究來源后,我發現事件偵聽器只有在上傳者上傳更多資料時才會被觸發。因為 Uploader 對上傳進行分塊,所以您有兩個單獨的配置引數,允許您將上傳分成單獨的塊。所以
const upload = new Upload({
client: s3,
params: target,
queueSize: 4, // 4 is minimum
partSize: 5*1024*1024 // 5MB is minimum
});
當我們上傳的檔案大于 5MB時,基本上可以完成這項作業!只有這樣事件才會再次觸發并更新狀態變數。
由于此上傳者處理大檔案上傳時,這完全是有道理的,我們可以簡單地調整queueSize,并partSize根據檔案,我們要上傳。就像是
let queueSize = 10;
const file = event.target.files[0];
let partSize = file.size / (10 * 1024 * 1024); // 1/10th of the file size in MB
const upload = new Upload({
client: s3,
params: target,
queueSize: partSize > 5 queueSize : undefined,
partSize: partSize > 5 ? partsize : undefined
});
顯然,這可以做得更復雜,但我不想花太多時間在這上面,因為它不是原始問題的一部分。
結論
如果您的檔案足夠大(>5MB),您將看到進度更新,具體取決于您選擇拆分檔案的塊數(5MB 或更多)。
由于這僅影響handleChange原始示例中的方法,因此我將其發布以保持完整性
const handleChange = async ( event ) => {
const file = event.target.files[0]
const target = {
Bucket: 'some-S3-bucket',
Key: `jobs/${file.name}`,
Body: file,
};
const s3 = new S3Client({
region: 'your-region',
credentials: fromCognitoIdentityPool({
client: new CognitoIdentityClient({ region: 'your-region' }),
identityPoolId: "your-id",
}),
});
// this will default to queueSize=4 and partSize=5MB
const upload = new Upload({
client: s3,
params: target
});
upload.on("httpUploadProgress", progress => {
console.log('Current Progress', progress);
setProgr(progress);
});
await upload.done().then(r => console.log(r));
}
也許這可以幫助有同樣問題的人。
uj5u.com熱心網友回復:
我今天遇到了完全相同的問題(使用 Vue)后找到了您的答案!
確實,您是對的:AWS SDK JS v3 事件僅觸發每個部分,這一點都不清楚,我也浪費了時間除錯。就像 4MB 的檔案一樣,它只會以 100% 的速度觸發。
正如您所說,您可以嘗試使用部分大小,但最小為 5MB,因此在連接速度較慢的情況下,我發現上傳似乎卡住了,因為您必須等待 5MB 才能獲取任何資料。唔。所以我所做的是查看正在上傳的檔案的大小。如果它低于閾值(例如 25MB 或任何適用的大小),那么一次性上傳所有內容可能是安全的,因為您實際上并不需要分段上傳。所以我還制作了一個預先簽名的 URL(https://aws.amazon.com/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/),它可以用于使用 axios 進行 PUT(因為fetch沒有支持進度事件)。
這樣您就可以upload用于大檔案(您實際上需要分段上傳,并且檔案大小的百分比為 5MB 較小),并為小檔案使用預先簽名的 URL,從而獲得更頻繁的更新。
兩者都可以使用相同的進度事件處理程式。
this.$axios
.request({
method: "PUT",
url: SIGNED-URL-HERE,
data: file,
timeout: 3600 * 1000,
onUploadProgress: this.uploadProgress,
})
.then((data) => {
console.log("Success", data);
})
.catch((error) => {
console.log("Error", error.code, error.message);
});
不理想,但它有幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/365078.html
