Загрузка большого zip-файла в хранилище Azure приводит к повреждению файла - PullRequest
0 голосов
/ 10 мая 2019

Использование Express с Node для загрузки ~ 800 МБ zip-файлов в хранилище Azure. Я использую пакет 'Azure-Storage' (https://www.npmjs.com/package/azure-storage)) для подключения и загрузки / выгрузки в хранилище Azure. Файл загружается через приложение Angular, разделяется на 10 МБ и передается в приложение Node. Я пробовал следующие способы:

  1. Получить все куски на узле (в виде потока байтов), объединить их в один zip-файл (я убедился, что созданный zip-файл является правильным) и сохранить его локально. Затем я загружаю объединенный файл в хранилище Azure. Проблема с этим подходом:
    • когда я сохраняю его как файл в Azure, файлы сохраняются, но если размер файла составляет 100 МБ +, целостность zip-файла не сохраняется. Размер файла правильный, но он не распаковывается при загрузке (отлично работает при небольшом размере файла)
    const azure = require('azure-storage');
    const blobService = azure.createBlobService(<STORAGE_ACCOUNT>, <STORAGE_ACCESS_KEY>);
    const fileService = azure.createFileServiceazure.createBlobService(<STORAGE_ACCOUNT>, <STORAGE_ACCESS_KEY>);

    fileService.createShareIfNotExists(
        <task_name>,
        (error, result, response) => {
          if (!error) {
            fileService.createDirectoryIfNotExists(
              <task_name>,
              <directory_name>,
              (error, result, response) => {
                if (!error) {
                  fileService.createFileFromLocalFile(
                    <task_name>,
                    <directory_name>,
                    <file_name>,
                    <path_to_local_file>,
                    (error, result, response) => {
                      if (!error) {
                        res.status(200).json({message: "Uploaded"});
                      } else {
                        console.log(error);
                      }
                    });
                }
              });
          }
    });
  • когда я сохраняю его как BLOB-объект в Azure, большие файлы вообще не загружаются, тогда как маленькие файлы работают нормально
    blobService.createContainerIfNotExists(
      <container_name>,
      {publicAccessLevel: 'blob'},
      (error, result, response) => {
        if (!error) {
          blobService.createBlockBlobFromLocalFile(
            <container_name>,
            <blob_name>,
            <path_to_local_file>,
            (error, result, response) => {
              if (!error) {
                res.status(200).json({message: "Uploaded"});
              } else {
                console.log(error);
              }
            });
        }
      });
  1. После объединения кусков в один файл, как упоминалось выше, я создаю поток чтения и передаю его в Azure. Результат тот же, что и выше - работает для маленьких файлов, но не для больших файлов
    fileService.createShareIfNotExists(
        <task_name>,
        (error, result, response) => {
          if (!error) {
            fileService.createDirectoryIfNotExists(
              <task_name>,
              <directory_name>,
              (error, result, response) => {
                if (!error) {
                  fileService.createFileFromStream(
                    <task_name>,
                    <directory_name>,
                    <file_name>,
                    <read_stream>,
                    <stream_length>,
                    (error, result, response) => {
                      if (!error) {
                        res.status(200).json({message: "Uploaded"});
                      } else {
                        console.log(error);
                      }
                    }
                  )
              }
            });
        }
    });
  1. Сохраняйте фрагменты в Azure по мере их получения (в идеале я хочу сделать это, поскольку мне не нужно будет создавать файл на диске). Первый блок загружен, но последующие блоки не загружаются
    blobService.createContainerIfNotExists(
      <container_name>,
      {publicAccessLevel: 'blob'},
      (error, result, response) => {
        if (!error) {
          blobService.createAppendBlobFromStream(
            <container_name>,
            <blob_name>,
            <read_stream>,
            <stream_length>,
            (error, result, response) => {
              if (!error) {
                res.status(200).json({message: "Uploaded"});
              } else {
                console.log(error);
              }
            });
        }
      });

Я тоже пробовал createPageBlobFromStream, но безуспешно.

Я не думаю, что multiform или CORS могут быть проблемой, так как загрузка из локального файла работает нормально для небольших файлов.

Редактировать Я смог найти решение одной из моих проблем - Мне просто нужно было увеличить «тайм-аут запроса» для запроса от моего внешнего интерфейса до внутреннего. В контроллере:

exports.uploadToAzure = (req, res, next) => {
    req.setTimeout(5000000); //initially set a high timeout

    //your code with proper error handling

    res.status(200);
};

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

Но я все еще не могу использовать метод appendFromStream для добавления потоков по мере их поступления и обхода их сохранения на диске. Любые мысли о том, как я могу использовать этот метод? Благодарю.

...