(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. Вам нужно разбить файл на куски.