Pomocou pokrok handler, keď nahrávate súbory na AWS S3 Reagovať

0

Otázka

Ja som len nedávno sa zaoberajú AWS SDK a preto prosím ospravedlňte, ak môj prístup je úplný nezmysel.

Chcem nahrať jednoduchý mediálny súbor moja S3. Bol som nasledujúce tento návod a doteraz som schopný nahrávať súbory bez problémov. Pre userbility pokrok bar by byť pekný extra a preto som skúmal, ako to dosiahnuť. Rýchlo som zistil, že súčasné AWS SDK v3 nepodporuje httpUploadProgress by sme však mali používať @aws-sdk/lib-storage namiesto toho. Pomocou tejto knižnice, som stále schopný nahrávať súbory na S3, ale nemôžem si pokrok tracker do práce! Predpokladám, že to má čo do činenia so mnou nie je plne pochopiť, ako sa vysporiadať s async v rámci Reagovať komponentu.

Takže tu je môj minified komponent príklad: (ja používam Čakra UI tu)

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;

Takže v podstate som sa pozri prípade dostať padáka (začnite nahrávanie súboru). Potom to chvíľu trvá a vidím Sľub výsledok a Progress, 100 v mojom konzoly. To pre mňa znamená, že štát premennej dostane aktualizované (aspoň raz), ale komponent nie je re-vykreslenie?

Čo je to, čo robím zle? Akákoľvek pomoc ocenia!

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

Najlepšiu odpoveď

1

V poriadku, som našiel riešenie. Spätné volanie o štátnej premennej funguje a robí to, čo by mala. Ale konfigurácie Upload objekt bol vypnutý. Po kopanie do zdroja som sa dozvedel, že v prípade poslucháč dostane len spustí, ak nahral odovzdal viac údajov. Pretože Uploader kusy na obrázky máte dve samostatné config parametre, ktoré umožňujú rozdeliť odovzdať do samostatných častí. Tak

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

v podstate robí svoju prácu, keď súbor sme upload je väčšie ako 5 MB! Len potom prípade dostane znovu aktivovať a aktualizácie stavu premennej.

Od tejto uploader je vyrobený pre manipuláciu veľké uploadovať súbory, tento úplne zmysel a mohli sme sa jednoducho nastaviť queueSize a partSize podľa súboru chceme odovzdať. Niečo ako

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

Samozrejme, to sa dá urobiť oveľa sofistikovanejšie, ale ja som nechcel tráviť príliš veľa času na to, pretože to nie je súčasťou pôvodnej otázke.

Záver

Ak váš súbor je dostatočne veľké (>5 MB), uvidíte pokrok aktualizácia, v závislosti od počtu kusov (z 5 MB alebo viac), ktoré ste sa rozhodli rozdeliť súbor.

Pretože to má vplyv len na handleChange metóda z pôvodného príklad, som tento post pre úplnosť

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

Možno to pomôže niekomu, kto má rovnaký problém.

2021-11-22 18:06:15
1

Narazil som na odpoveď po tom, ako presne rovnaký problém (s Vue) dnes!

Naozaj ste doprava: AWS SDK JS v3 udalosť len požiarov na časť , ktorá nie je vôbec jasné, a som stratený čas ladenie, že príliš. Ako pre 4MB súbor, to by len niekedy oheň na 100%.

Ako hovoríte, môžete experimentovať s časti veľkosť , ale minimum je 5 MB a tak na pomalé spojenia som zistil, že sa môže objaviť, že odovzdanie sa zasekol, pretože budete musieť čakať na 5 MB získať žiadne údaje. Hmm. Takže to, čo som urobil, bolo pozrieť na veľkosť súboru, nahrané. A ak je pod prahom (povedzme 25MB, alebo čo je to uplatniteľné), no to je pravdepodobne bezpečné odovzdanie, že všetky naraz ako nepotrebujete zložené nahrávanie. A tak som aj urobil presigned URL (https://aws.amazon.com/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/), ktoré môžu byť použité, aby sa DAL pomocou axios (od fetch nepodporuje pokrok udalosti zatiaľ).

Tak, že spôsob, ako môžete používať upload pre veľké súbory (ak skutočne potrebujete zložené nahrávanie a kde je 5 MB ako percento veľkosť súboru je malý), a používať presigned URL pre malé súbory, a tak získať oveľa viac časté aktualizácie.

Rovnaký pokrok obsluhu udalosti môže byť použitý na oboch.

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

Nie je ideálny, ale pomáha.

2021-11-24 00:54:55

Mal som rovnaký nápad, ale aby sme boli spravodliví, myslím, že lib-storage nikdy nebolo malo byť použitý pre malé uploadovať súbory. Bohužiaľ, zdá sa, že v súčasnosti nie je uspokojujúce riešenie pri použití v3 (pretože je to pomocou fetch api pod kapotu) a nahrávanie malé súbory. Takže váš prístup je určite dobré riešenie, ale dúfajme, že sa bude realizovať niečo v SDK veľmi skoro.
Flo Ragossnig

Súhlasím. Je to nepríjemné toho, aby museli používať podpísané URL ako riešenie, ale ak/do SDK zmeny (možno keď preberal API pridá upload pokrok) teraz zdá sa, že máte vybrať v závislosti od toho, či už zložené alebo pravidelné pokrok aktualizácie je najdôležitejšie, aby vaše používanie
coder_uk

V iných jazykoch

Táto stránka je v iných jazykoch

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