(413) Тело запроса слишком велико и превышает максимально допустимый предел. Потоковая передача Zip в хранилище больших двоичных объектов с использованием ICSharpCode.SharpZipLib

Мне нужно создать большой zip-файл в моем хранилище BLOB-объектов Azure, используя мои файлы в другом контейнере в том же хранилище BLOB-объектов Azure. Количество файлов может составлять сотни тысяч и несколько гигабайт данных.

Используя WindowsAzure.Storage и SharpZipLib, я написал следующий код:

<package id="WindowsAzure.Storage" version="7.2.1" targetFramework="net461" />
<package id="SharpZipLib" version="1.0.0" targetFramework="net461" />

-

CloudBlobContainer backupContainer = _myservice.GetBlobBackupContainer();
tempZipBlockBlob = container.GetBlockBlobReference(Path.Combine(MyBlobStoragePaths.BackupsTempFolder, backupId));
tempZipBlockBlob.DeleteIfExists();
using (CloudBlobStream blobStream = tempZipBlockBlob.OpenWrite(AccessCondition.GenerateIfNotExistsCondition()))
{
  using (var zipOutputStream = new ZipOutputStream(blobStream))
  {
            zipOutputStream.SetLevel(0);
            foreach (CloudBlockBlob cloudBlob in snapshots)
            {
                string blobName = Path.Combine(prefix, cloudBlob.Name.Replace('/', '\\'));
                try
                {
                    var buffer = new byte[4096];

                    using (Stream readStream = cloudBlob.OpenRead())
                    {
                        var zipEntry = new    ZipEntry(ZipEntry.CleanName(blobName)) {Size = readStream.Length};
                        zipOutputStream.PutNextEntry(zipEntry);
                        StreamUtils.Copy(readStream, zipOutputStream, buffer);
                     }
                  zipOutputStream.Flush();
                 }
                 catch (Exception e)
                 {
                   Log.Error(e, "CopySnapshotToZipOutputStream failed for   {blobName}.",  blobName);
                   throw;
                  }
              }
  }
}

Код отлично работает в моем dev и на тесте для многих контейнеров, но не работает для 1.

Microsoft.WindowsAzure.Storage.StorageException: удаленный сервер возвратил ошибку: (413) Тело запроса слишком велико и превышает максимально допустимый предел. ---> System.Net.WebException: удаленный сервер возвратил ошибку: (413) Тело запроса слишком велико и превышает максимально допустимый предел. [17.10.2008 14:55:11 > 9d4928: INFO] в T Microsoft.WindowsAzure.Storage.Shared.Protocol.HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode Ожидаемый StatusCode, HttpStatusCode actualStatusCode, T retVal, StorageCommandBase cmd, Exception ex) в c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\Common\Shared\Protocol\HttpResponseParsers.Common.cs: строка 50 [10/17/2018 14:55:11 > 9d4928: INFO] в RESTCommand Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.PutBlockImpl(Потоковый источник, строковый blockId, строковое содержимое MD5, AccessCondition accessCondition, параметры BlobRequestOptions)+(RESTCommand, исключение, Http, OperationContext ctx) => { } в c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Blob\CloudBlockBlob.cs: строка 2380 [17.10.2008 14:55:11> 9d4928: ИНФОРМАЦИЯ ] в void Microsoft.WindowsAzure.Storage.Core.Executor.Executor.EndGetResponse(IAsyncResult getResponseResult) в каталоге c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\ line9. Executor. [17.10.2008 14:55:11 > 9d4928: INFO] --- Конец трассировки стека внутренней исключительной ситуации --- [17.10.2008 14:55:11 > 9d4928: INFO] в void Microsoft.WindowsAzure.Storage.Blob.BlobWriteStream.Flush() в c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Blob\BlobWriteStream.cs: строка 234 [17.10.2008 14:55:11 > 9d4928: INFO] at void ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream.Finish() [17.10.2008 14:55:11 > 9d4928: INFO] в void ICSharpCode.SharpZipLib.Zip.ZipOutputStream.lose 17.10.2008 14:55:11> 9d4928: ИНФОРМАЦИЯ] в void ICSharpCode.SharpZipLib.Zip.ZipOutputStream.PutNextEntry(запись ZipEntry)

Я проверил клиента, и у меня есть больше журналов. Там общий размер файлов, которые я пытаюсь сжать, составляет всего 3,7 ГБ, и есть только ~68 000 файлов, которые я пытаюсь сжать.

Сбой на небольшом jpg-файле размером всего 4,16 КБ: \ и он правильно передал более 49 000 файлов в потоке zip.

Кроме того, с помощью того же WindowsAzure.Storage SDK я мог легко загрузить на свой компьютер большие двоичные объекты и сжать их в локальный zip-файл, а затем использовать метод UploadBlob.

Есть идеи, что может быть причиной проблемы?

Обновить

Я вижу, что существует ограничение в 50 000 блоков на каждый блоб. Мои файлы очень маленькие, поэтому я не ожидал, что каждый из них займет по 1 блоку, но возможно ли, что при вызове zipOutputStream.PutNextEntry(zipEntry); Я открываю новый блок?

Если это так, как я могу это исправить?

1 ответ

Согласно этой странице поддержки Microsoft существует ограничение в 4 МБ при использовании REST API или HTTPS PUT. Вам нужно разбить файл на куски.

Другие вопросы по тегам