En utilisant les progrès de gestionnaire lors du téléchargement de fichiers à AWS S3 à Réagir

0

La question

Je ne suis que récemment traitant avec le SDK AWS et donc s'il vous plaît excuser si mon approche est un non-sens complet.

Je veux télécharger un simple fichier multimédia de mon S3. J'ai suivi ce tutoriel et pour l'instant je suis en mesure de télécharger des fichiers sans problème. Pour userbility une barre de progression serait un plus agréable et donc j'ai été la recherche de moyens pour y parvenir. J'ai rapidement constaté que l' actuelle AWS SDK v3 ne prend pas en charge httpUploadProgress plus mais nous devrions utiliser @aws-sdk/lib-storage au lieu de cela. L'utilisation de cette bibliothèque, je suis encore capable de télécharger des fichiers sur le S3, mais je ne peux pas obtenir la progression tracker pour travailler! Je suppose que cela a quelque chose à voir avec moi, pas la pleine compréhension de la façon de traiter avec async au sein d'une Réagir composant.

Voici donc mon minifiés composant exemple (je suis en utilisant le Chakra de l'INTERFACE utilisateur ici)

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;

Donc, fondamentalement, je vois l'événement de se faire licencier (start upload de fichier). Puis il prend un certain temps et je vois la Promesse de résultat et de la Progress, 100 dans ma console. Cela signifie pour moi que la variable d'état est mis à jour (au moins une fois), mais de ne pas re-rendu?

Qu'est-ce que je fais de mal ici? Toute aide appréciée!

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

La meilleure réponse

1

Bon, j'ai trouvé la solution. Le rappel sur la variable d'état fonctionne très bien et fait ce qu'il doit. Mais la configuration de l' Upload l'objet était à l'arrêt. Après avoir creuser dans le code source, j'ai trouvé que l'écouteur d'événement seulement se déclenche si l'utilisateur a téléchargé plus de données. Car Uploader les morceaux les téléchargements que vous avez deux config paramètres qui vous permettent de diviser votre télécharger en différents morceaux. Donc

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

se fait de la tâche lorsque le fichier de téléchargement est de plus de 5 MO! Alors seulement, l'événement se déclenche à nouveau et met à jour la variable d'état.

Depuis ce chargeur est fabriqué pour le traitement de gros téléchargements de fichiers, c'est tout à fait compréhensible et nous avons pu régler simplement queueSize et partSize selon le fichier à télécharger. Quelque chose comme

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

Évidemment, cela peut être fait beaucoup plus sophistiqué, mais je n'ai pas envie de passer trop de temps sur cela, car il ne fait pas partie de la question d'origine.

Conclusion

Si votre fichier est assez volumineux (>5 MO), vous pourrez voir l'avancement des travaux de mise à jour, en fonction du nombre de morceaux (de 5 mo ou plus), vous avez choisi de diviser votre fichier.

Puisque cela n'affecte que la handleChange méthode à partir de l'exemple d'origine, je poste ce pour l'intégralité

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

Peut-être que cela aide quelqu'un qui a le même problème.

2021-11-22 18:06:15
1

Je suis tombé sur votre réponse après avoir exactement le même problème (avec Vue) aujourd'hui!

En effet, vous avez raison: le SDK AWS JS v3 événement ne se déclenche par une partie qui n'est pas clair du tout et j'ai perdu le temps de débogage que trop. Comme pour un fichier de 4 mo, il ne serait jamais le feu à 100%.

Comme vous le dites, vous pouvez expérimenter avec la taille de la pièce , mais le minimum est de 5 mo et donc sur une connexion lente, j'ai trouvé, il peut apparaître que le téléchargement est bloqué que vous avez à attendre pour 5MO à obtenir toutes les données. Hmm. Donc ce que j'ai fait a été de regarder la taille du fichier en cours de téléchargement. Et si elle est sous un seuil (dire 25MO, ou tout ce qui est applicable), eh bien, il est probablement sûr de télécharger tous en un rendez-vous que vous n'avez pas vraiment besoin de téléchargement en plusieurs parties. Et donc j'ai aussi fait une presigned URL (https://aws.amazon.com/blogs/developer/generate-presigned-url-modular-aws-sdk-javascript/) qui peut être utilisé pour METTRE à l'aide d'axios (depuis fetch ne prend pas en charge les progrès des événements encore).

Ainsi, vous pouvez utiliser upload pour les gros fichiers (où vous avez réellement besoin de téléchargement en plusieurs parties et où 5MO comme un pourcentage de la taille du fichier est de petite taille), et l'utilisation d'un presigned URL pour les petits fichiers et ainsi d'obtenir beaucoup plus de mises à jour fréquentes.

Les mêmes progrès gestionnaire d'événements peut être utilisé par les deux.

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

Pas l'idéal, mais ça aide.

2021-11-24 00:54:55

J'ai eu la même idée, mais pour être juste, je suppose lib-storage n'a jamais été destiné à être utilisé pour les petits de téléchargement de fichiers. Malheureusement, il semble qu'il n'existe actuellement aucune solution de satisfaction lors de l'utilisation de v3 (puisque c'est à l'aide de l'extraction de l'api sous le capot) et le téléchargement des fichiers de petite taille. Si votre approche est certainement une bonne solution, mais j'espère qu'ils vont mettre en place quelque chose dans le SDK très bientôt.
Flo Ragossnig

Je suis d'accord. C'est ennuyeux d'avoir à utiliser un signé de l'URL comme une solution de contournement mais, sauf si/jusqu'à ce que le SDK changements (peut-être lors de l'extraction de l'API ajoute l'avancement du téléchargement) pour l'instant, il semble que vous avez à choisir selon que multipart ou régulier de mises à jour de progression est la plus importante pour votre utilisation
coder_uk

Dans d'autres langues

Cette page est dans d'autres langues

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