ใช้เครื่องมือจัดการความคืบหน้าตอนที่กำลังอัพโหลดแฟ้มเพื่อ AWS S3 กับมีปฏิกิริยา

0

คำถาม

ฉันเป็นเพียงเมื่อเร็วๆนี้กำลังรับมือกับพว AWS SDK และดังนั้นโปรดยกโทษถ้าผมเข้าใกล้คือสมบูรณ์ไร้สาระน่า

ฉันต้องการที่จะอัพโหลดเรียบง่ายของสื่อแฟ้มของฉั S3. ฉันกำลังสะกดรอยตาม นี้ comment และตอนนี้ฉันสามารถอัพโหลดแฟ้มโดยไม่มีปัญหาแล้ว สำหรับ userbility เป็นความคืบหน้าบาร์จะดีที่พิเศษแล้วดังนั้นฉันค้นคว้าวิธีที่จะประสบความสำเร็จในส่วนี้ ฉันรีบพบว่าที่ ปัจจุบัน AWS SDK v3 ไม่รองรับ httpUploadProgress อีกแล้ว แต่พวกเราควรใช้ @aws-sdk/lib-storage แทน ใช้ห้องสมุดฉันยังคงสามารถอัพโหลดแฟ้มเพื่อที่ S3 แต่ฉันไม่สามารถได้รับความคืบหน้าแทร็กเกอร์ทำงาน! ฉันคิดว่ามีบางอย่างที่เกี่ยวกับฉันไม่ได้เต็มที่เข้าใจวิธีจัดการกับ async ภายในมีปฏิกิริยายส่วนประกอบ.

ดังนั้นนี่คือของฉัน minified ส่วนประกอบตัวอย่าง(ฉันใช้ Chakra ส่วนติดต่อผู้ใช้อยู่)

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 ในของฉันคอนโซล. มันมีความหมายกับฉันแค่ไหนที่ของรัฐตัวแปรได้ปรับปรุง(อย่างน้อยก็ครั้งนึงแต่คนส่วนประกอบยังไม่กลัจัดการพา?

มันคืออะไรสิ่งที่ฉันกำลังทำผิดอยู่ที่นี่? ที่เขาแนะนำให้ผูกผ้ากันเปื้อนเกียรติอย่างยิ่!

amazon-s3 aws-sdk reactjs
2021-11-22 15:34:31
2

คำตอบที่ดีที่สุด

1

เอาล่ะฉันต้องเจอทางออกหรอกนะ ที่เรียกกลับในเมืองตัวแปรทำงานได้ดีและสิ่งที่มันควรจะเป็นอย่างนั้น แต่การปรับแต่งของ Upload วัตถุนถูกปิด หลังจากขุดเข้าไปในแหล่งข่าวฉันพบว่าที่เหตุการณ์เดียวที่เป็นนักฟังที่จะกระตุ้นถ้า ค uploader มีอัพโหลดข้อมูลมากก. เพราะ Uploader นวนท่อนที่ค uploads คุณสองคนแยกออก config พารามิเตอร์ซึ่งอนุญาตให้คุณต้องแยกของคุณอัพโหลดไปนวนท่อนที่แยกออก. ดังนั้น

const upload = new Upload({
  client: s3,
  params: target,
  queueSize: 4,          // 4 is minimum
  partSize: 5*1024*1024  // 5MB is minimum
});

ง่ายๆก็คือทำงานเมื่อแฟ้มที่เราเคยอัพโหลดมั นใหญ่กว่า 5MB! หลังจากนั้นขึ้นอยู่กับเหตุการณ์ได้กระตุ้นอีกครั้งและปรับปรุงรัฐองตัวแปร

ตั้งแต่นี้ uploader คือทำให้การจัดการแฟ้มใหญ่ uploads มันสมเหตุสมผลและพวกเราได้อย่างง่ายปรับแก้ 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 วิธีการจากต้นฉบับตัวอย่างเช่นฉันโพสต์สิ่งนี้เพื่อ completeness

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));
} 

บางทีนี่อาจจะช่วยใครบางคนที่มีปัญหาเดียวกัน

2021-11-22 18:06:15
1

ฉันเจอคำตอบของคุณหลังจากมีคนเดียวกันแน่นอปัญหาได้(กับ Vue)วันนี้!

แน่นอนคุณพูดถูกนะ AWS SDK JS v3 เหตุการณ์เพียงเพลิงต่อ ส่วนหนึ่ง ซึ่งไม่ใช่ตอนทุกอย่างเรียบร้อยและฉันเสียเวลาเวลาที่ดีบั๊กโปรแกรมที่เหมือนกัน เหมือนเป็น 4MB แฟ้มมันคงเดียวลปืนที่เก่งที่สุด..เคยยิงตอ 100%.

อย่างที่คุณพูดว่าคุณสามารถทดลองกับคนส่วนหนึ่งขนาดขอ แต่ งน้อยที่สุดคือ 5MB ขึ้นก่อการเชื่อมต่อฉันเจอมันสามารถปรากฏว่าการอัปโหลดติดอยู่อย่างที่คุณต้องรอสำหรับ 5MB จะ มี ข้อมูล หืมมม ดังนั้นสิ่งที่ฉันทำคือดูขนาดของแฟ้มที่อัปโหลดไป. และถ้ามันเป็นอยู่ใต้จุด(พูด 25MB หรืออะไรก็ตามที่เป็นกทำได้),เอ่อมันอาจจะปลอดภัยที่จะอัพโหลดมันทั้งหมดในหนึ่งไปอย่างที่คุณไม่ต้องการจริงๆ multipart กำลังอัพโหลด และดังนั้นฉัน ก็ ทำ presigned ที่อยู่ URL(https://aws.amazon.com/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/)ซึ่งสามารถใช้เพื่อทำให้ใช้ axios(ตั้งแต่ fetch ยังไม่รองรับความคืบหน้าเหตุการณ์ยัง).

ดังนั้นทางคุณสามารถใช้ upload สำหรับขนาดใหญ่กแฟ้ม(อยู่ไหนคุณจริงๆต้อง multipart กำลังอัพโหลดและที่ไหนที่ 5MB โดยมีหน่วยเป็นเปอร์เซ็นต์ของขนาดแฟ้มเล็ก)และใช้ presigned ที่อยู่ 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);
  });

ไม่ใช่ที่ฝันไว้แต่มันช่วยได้

2021-11-24 00:54:55

ฉันต้องคิดเหมือนกันแต่จะเป็นไปอย่างยุติธรรมฉันคิดว่า lib-storage มันไม่เหมาะที่จะใช้สำหรับแฟ้มเล็ uploads. โชคร้ายที่มันดูเหมือนมีอยู่ปัจจุบันที่ไม่พอใจแก้ปัญหาเมื่อใช้ v3 (ตั้งแต่มันใช้อข้อมูลรูปแบบ api องใต้กระโปรงและการอัพโหลดเล็กน้องแฟ้ม ดังนั้นวิธีการของคุณเป็นอย่างแน่นอที่ดี workaround แต่หวังว่าพวกเขาจะรับคำสั่งเข้าใจบางอย่างใน SDK เร็วๆนี้
Flo Ragossnig

ฉันเห็นด้วย มันน่ารำคาญที่ต้องใช้เซ็นที่อยู่ URL ที่ workaround แต่นอกจาก/จนกระทั่ง SDK เปลี่ยนแปลง(บางทีตอนที่เอารูปแบบ api เพิ่มอัปโหลดความคืบหน้า)สำหรับตอนนี้มันดูเหมือนว่าคุณต้องเลือกมันขึ้นอยู่กับ\อันว่า multipart หรือธรรมดาความคืบหน้าปรับปรุงเป็นที่สำคัญที่สุดของคุณสลับหน้าพื้นที่ทำงาน name
coder_uk

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................