загрузка файла s3 — не работает для video — React / Meteor — aws-sdk

#node.js #reactjs #amazon-s3 #meteor #aws-sdk

#node.js #reactjs #amazon-s3 #метеор #aws-sdk

Вопрос:

У меня возникла проблема с загрузкой файлов mp4 в мою корзину s3 в моем проекте react / meteor. Это работает для файлов другого типа (mp3, изображений), но не для видео. Я не получаю никаких ошибок, но когда я пытаюсь прочитать загруженный файл, он не работает.

вот мой клиентский код:

 import React from "react";
import { Meteor } from "meteor/meteor";
import PropTypes from "prop-types";
import { types } from "../../../utils/constants/types";

const FileUpload = ({ fileType, type, typeId, subtype, setFileName }) => {
  const handleUpload = event => {
    event.preventDefault();
    const file = event.target.files[0];
    const fileExtension = file.type;
    var reader = new FileReader();
    reader.onload = function () {
      Meteor.call(
        "uploadFile",
        fileExtension,
        reader.result,
        type,
        typeId,
        (err, result) => {
          if (err) {
            console.log(err);
          } else {
            setFileName(result);
          }
        }
      );
    };
    reader.readAsDataURL(file);
  };

  return (
    <div>
      <input name="Uploader" onChange={handleUpload} type="file" />
    </div>
  );
};
  

и на стороне сервера есть мой метод meteor:

 Meteor.methods({
  uploadFile: async function (fileType, data, type, typeId) {
    let extension;
    let contentType = fileType;

      if (fileType.includes("jpeg") || fileType.includes("jpg")) {
        extension = "jpg";
      } else if (fileType.includes("png")) {
        extension = "png";
      } else if (fileType.includes("mp4")) {
        extension = "mp4";
      } else if (fileType.includes("audio/mpeg")) {
        contentType = "video/mp4";
        extension = "mp3";
      } else if (fileType.includes("pdf")) {
        extension = "pdf";
      } else {
        throw new Meteor.Error("format-error", "Only authorized format");
      }

      const random = Random.id();
      const key = `random.${extension}`;

      const buf =
        extension !== "mp4"
          ? Buffer.from(data.replace(/^data:image/w ;base64,/, ""), "base64")
          : data;

      const config = {
        Bucket: bucketName,
        Key: key,
        Body: buf,
        ContentType: contentType,
        ACL: "public-read",
      };

      if (extension !== "mp4") {
        config.ContentEncoding = "base64";
      }
      const uploadResult = await s3.upload(config).promise();
      return uploadResult.Location;

  },
});
  

Я думаю, что это может быть связано с тем, что читатель неправильно управляет видеофайлами, но я немного заблудился. Любой вклад будет оценен. Спасибо.

Комментарии:

1. Файл отсутствует или содержимое плохое?

2. контент, по-видимому, плохой. Предполагается, что это 4-секундное видео, и я ничего не получаю (0 секунд)

3. Вы уверены onload , что обратный вызов запускается, когда вы думаете, что это так? Что произойдет, если вы просто вручную вызовете uploadFile после загрузки данных?

4. как уже упоминалось, код работает для изображений и mp3, только mp4 как-то не работает.

5. @Exelian также я могу получить файл с помощью wget, и его размер нормальный, но он может воспроизводиться локально.

Ответ №1:

Я хотел спросить, поскольку я вижу, что ваш код довольно сложный. Почему вы загружаете файлы через свой сервер?

Я думаю, что более эффективно отправлять файлы с клиента прямо на S3. Пожалуйста, взгляните на этот пакет, который я поддерживаю, если вам интересно ознакомиться с концепцией (https://github.com/activitree/s3up-meta ). Это перезапись старого, проверенного годами пакета. Загрузка подписывается сервером Meteor, но загружается клиентом. Вы не хотите, чтобы сокеты / волокна были заняты загрузкой файлов, в то время как для каждой загрузки поступает много данных (данные о статусе загрузки). Вы хотели бы иметь все это на стороне пользователя / клиента.

Еще одна вещь, на которую следует обратить внимание, — это важность настройки AbortIncompleteMultipartUpload в вашем ведре / управлении / жизненном цикле. В этом случае размер вашего S3 может увеличиваться без контроля.

Наконец, когда я загружаю видео, я просто загружаю файл (полученный из файла входного типа). Это выглядит так:

 video: File
   lastModified: 1573722339000
   lastModifiedDate: Thu Nov 14 2019 13:05:39 GMT 0400 (Gulf Standard Time) {}
   name: "IMG_7847.MOV"
   size: 20719894
   type: "video/quicktime"
   webkitRelativePath: ""

  

Я использую другие помощники для определения файла (и ограничения продолжительности разрешенных загрузок) и типа файла.

Вы можете отслеживать ошибки на стороне вашего сервера при загрузке или / и активировать CloudWatch на стороне S3, чтобы увидеть, где что-то не работает.

Комментарии:

1. Я проверю ваше решение, мне нравится идея загружать напрямую с клиента, просто получив авторизацию с сервера.