C # перенос файлов из MongoDB в хранилище BLOB-объектов Azure с использованием метода «UploadFromStream» не работает - PullRequest
0 голосов
/ 01 апреля 2019

У меня проблемы с переносом файлов из хранилища BLOB-объектов MongoDB 2 Azure.

Следующий метод получает объект GridFSFile (который представляет файл в MongoDB GridFSFileStorage), а затем вызывает метод uploadMemoryStream для выполнения загрузки.

Стоит отметить, что gridFSFile имеет содержимое после findById, и что длина dow также имеет содержимое, и эта позиция изначально равна 0.

Метод gridFSFile.Open создает объект Stream, который я затем передаюв качестве аргумента для загрузки.

private static void iterateOverVersionCollection(Version version, Asset asset)
{
    try
    {    
        string _gridFSId = version.GridFSId;
        GridFSFile gridFSFile = gridFSFileStorage.FindById(_gridFSId);
        if (gridFSFile == null) return;

        string size = version.Name.ToLower();
        asset.Size = size;
        CloudBlockBlob blockBlob = GetBlockBlobReference(version, gridFSFile, asset);
        uploadMemoryStream(blockBlob, gridFSFile, asset);
        asset.UploadedOK = true;
    }
    catch (StorageException ex)
    {
        asset.UploadedOK = false;
        logException(ex, asset);
    }
}

private static void uploadMemoryStream(CloudBlockBlob blockBlob, GridFSFile gridFSFile, Asset asset)
{
      Stream st = gridFSFile.Open();
      blockBlob.UploadFromStream(st);
}

UploadFromStream занимает вечность и никогда не выполняет загрузку, и следует упомянуть одну вещь: независимо от того, как я работаю с gridFSFile, я пытаюсь создать MemoryStream с его помощьюStream.copyTo c # метод также работает вечно и никогда не заканчивается, поэтому приложение застревает в blockBlob.UploadFromStream (st);

Вместо того, чтобы просто передавать gridFSFile.Open to UploadFromMemoryStream Я также попробовал следующий кусоккода:

using (var stream = new MemoryStream())
{
    byte[] buffer = new byte[2048]; // read in chunks of 2KB
    int bytesRead;
    while((bytesRead = st.Read(buffer, 0, buffer.Length)) > 0)
    {
        stream.Write(buffer, 0, bytesRead);
    }
    byte[] result = stream.ToArray();
}

Но то же самое, программа получаетзастрял в st.Read линии.

Любая помощь будет высоко ценится.

1 Ответ

0 голосов
/ 02 апреля 2019

Обратите внимание, что поскольку UploadFromFileAsync () или UploadFromStream не является надежной и эффективной операцией для огромного большого двоичного объекта, я предлагаю вам рассмотреть следующие варианты:

Если вы можете принять инструмент командной строки, вы можете попробовать AzCopy, который способен передавать данные хранилища Azure с высокой производительностью, и его передача может быть приостановлена ​​и возобновлена.

Если вы хотите управлять передачей заданий программным способом, используйте Библиотека перемещения данных хранилища Azure , которая является ядром AzCopy. Пример кода для того же

string storageConnectionString = "myStorageConnectionString";
     CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
      CloudBlobClient blobClient = account.CreateCloudBlobClient();
      CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainer");
      blobContainer.CreateIfNotExistsAsync().Wait();
      string sourcePath = @"C:\Tom\TestLargeFile.zip";
      CloudBlockBlob destBlob = blobContainer.GetBlockBlobReference("LargeFile.zip");
      // Setup the number of the concurrent operations
      TransferManager.Configurations.ParallelOperations = 64;
      // Setup the transfer context and track the upoload progress
      var context = new SingleTransferContext
      {
          ProgressHandler =
          new Progress<TransferStatus>(
               progress => { Console.WriteLine("Bytes uploaded: {0}", progress.BytesTransferred); })
       };
      // Upload a local blob
      TransferManager.UploadAsync(sourcePath, destBlob, null, context, CancellationToken.None).Wait();
      Console.WriteLine("Upload finished !");
      Console.ReadKey();

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

var container = _client.GetContainerReference("test");
container.CreateIfNotExists();
var blob = container.GetBlockBlobReference(file.FileName);
var blockDataList = new Dictionary<string, byte[]>();
using (var stream = file.InputStream)
{
    var blockSizeInKB = 1024;
    var offset = 0;
    var index = 0;
    while (offset < stream.Length)
    {
        var readLength = Math.Min(1024 * blockSizeInKB, (int)stream.Length - offset);
        var blockData = new byte[readLength];
        offset += stream.Read(blockData, 0, readLength);
        blockDataList.Add(Convert.ToBase64String(BitConverter.GetBytes(index)), blockData);

        index++;
    }
}

Parallel.ForEach(blockDataList, (bi) =>
{
    blob.PutBlock(bi.Key, new MemoryStream(bi.Value), null);
});
blob.PutBlockList(blockDataList.Select(b => b.Key).ToArray());

с другой стороны, если у вас есть файл, доступный в вашей системе, и вы хотите использовать метод Uploadfile, у нас также есть гибкость в этом методе для загрузки данных файлов кусками

TimeSpan backOffPeriod = TimeSpan.FromSeconds(2);
int retryCount = 1;
BlobRequestOptions bro = new BlobRequestOptions()
{
  SingleBlobUploadThresholdInBytes = 1024 * 1024, //1MB, the minimum
  ParallelOperationThreadCount = 1, 
  RetryPolicy = new ExponentialRetry(backOffPeriod, retryCount),
};
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
cloudBlobClient.DefaultRequestOptions = bro;
cloudBlobContainer = cloudBlobClient.GetContainerReference(ContainerName);
CloudBlockBlob blob = cloudBlobContainer.GetBlockBlobReference(Path.GetFileName(fileName));
blob.StreamWriteSizeInBytes = 256 * 1024; //256 k
blob.UploadFromFile(fileName, FileMode.Open);

Для подробного объяснения, пожалуйста, просмотрите

https://www.red -gate.com / простой разговор / облака / платформа-как-сервис / лазурь-шарикообразным хранение части-4-загрузка-большой-сгустки /

Надеюсь, это поможет.

...