1
votes

Azure blockBlobURL.download () a-t-il une limite de taille de fichier?

J'utilise blockBlobURL.download () d'Azure pour télécharger une image, mais je ne reçois que la partie supérieure de l'image. Y a-t-il une limite à la quantité que je peux télécharger à partir de l'objet blob Azure vers un flux lisible? La longueur du contenu est 172628 et il existe une propriété highWaterMark: 16384 . Sont-ils liés?

async function compareToBaseline(imageData, blobName, metadata){

  const baselineBlobName = "MacOSX10.12/chrome/initial"

  const containerURL = ContainerURL.fromServiceURL(serviceURL, "baselines")
  const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, baselineBlobName );
  let baseLineImage = await blockBlobURL.download(aborter, 0)

  baseLineImage = baseLineImage.originalResponse.readableStreamBody.read()
  console.log(baseLineImage.length);

  baseLineImage = new Buffer(baseLineImage, 'base64');
  await fs.writeFile('./newest.png', baseLineImage, 'binary', function(err){
    console.log('written');
  })
}

Le résultat n'est que la partie supérieure d'une image.


4 commentaires

Je ne peux pas écrire une réponse correcte pour le moment, mais read () ne renvoie qu'un morceau de données, vous devez boucler jusqu'à ce qu'il renvoie null , voir docs


Serais-je capable de boucler sur ces données et de continuer à ajouter les données à une variable et éventuellement d'écrire ces données dans le système de fichiers? Ou aurais-je besoin de le diriger en continu vers le système de fichiers? Si je comprends bien.


Idéalement, vous les dirigeriez vers le système de fichiers au lieu de placer d'abord les données dans une variable, afin de limiter la consommation de mémoire. Dans ce cas, vous n'aurez probablement même pas besoin d'appeler read () dans une boucle, je suppose que fs prend en charge l'écriture d'un flux directement dans un fichier.


read () renvoie null ne signifie pas qu'il n'y a plus de données dans le flux. Vous devez suivre les pratiques de Node.js pour obtenir toutes les données en écoutant l'événement data ou readable . Par exemple, readable.on ('readable', () => {let chunk; while (null! == (chunk = readable.read ())) {console.log ( Received $ { chunk.length} octets de données. );}});


3 Réponses :


0
votes

Il existe une limite de 4 Mo pour chaque appel au service de stockage Azure. Si votre fichier est supérieur à 4 Mo, vous devez le découper en morceaux. Pour plus d'informations, consultez Évolutivité et objectifs de performances du stockage Azure a >.

Voici un exemple de code c # pour télécharger de très gros fichiers par blocs de 1 Mo. il est également axé sur les performances.

var azure = require('azure-storage');
var fs = require('fs');

module.exports = function (context, input) {

context.done();

var accessKey = 'myaccesskey';
var storageAccount = 'mystorageaccount';
var containerName = 'mycontainer';

var blobService = azure.createBlobService(storageAccount, accessKey);

var recordName = "a_large_movie.mov";
var blobName = "standard/mov/" + recordName;

var blobSize;
var chunkSize = (1024 * 512) * 8; // I'm experimenting with this variable
var startPos = 0;
var fullPath = "D:/home/site/wwwroot/myAzureFunction/input/";
var blobProperties = blobService.getBlobProperties(containerName, blobName,   null, function (error, blob) {
    if (error) {
        throw error;
    }
    else    {
        blobSize = blob.contentLength;
        context.log('Registered length: ' + blobSize);
        fullPath = fullPath + recordName;
        console.log(fullPath);
        doDownload();
    }
}
);

function doDownload() {
var stream = fs.createWriteStream(fullPath, {flags: 'a'});
var endPos = startPos + chunkSize;
if (endPos > blobSize) {
    endPos = blobSize;
    context.log('Reached end of file endPos: ' + endPos);
}

context.log("Downloading " + (endPos - startPos) + " bytes starting from " + startPos + " marker.");

blobService.getBlobToStream(
    containerName, 
    blobName, 
    stream, 
    { 
        "rangeStart": startPos, 
        "rangeEnd": endPos-1 
    }, 
    function(error) {
        if (error) {
            throw error;
        }
        else if (!error) {
            startPos = endPos;
            if (startPos <= blobSize - 1) {
                doDownload();
            }
        }
    }
);
}

};

Quelque chose comme ci-dessous dans node js

 private static void DownloadLargeFile()
        {
            string connectionString = "connString"; //ConfigurationSettings.AppSettings["StorageConnectionString"]; //blob connection string
#pragma warning restore CS0618 // Type or member is obsolete
#pragma warning disable CS0618 // Type or member is obsolete
            string sourceContainerName = "quickstartblob"; //ConfigurationSettings.AppSettings["sourcecontainerName"]; //source blob container name            
#pragma warning restore CS0618 // Type or member is obsolete
            string sourceBlobFileName = "QuickStart1.txt"; //source blob name
            CloudStorageAccount account = CloudStorageAccount.Parse(connectionString);
            var blobClient = account.CreateCloudBlobClient();
            var container = blobClient.GetContainerReference(sourceContainerName);
            var file = sourceBlobFileName;
            var blob = container.GetBlockBlobReference(file);
            //First fetch the size of the blob. We use this to create an empty file with size = blob's size
            blob.FetchAttributes();
            var blobSize = blob.Properties.Length;
            long blockSize = (1 * 1024 * 1024);//1 MB chunk;
            blockSize = Math.Min(blobSize, blockSize);
            //Create an empty file of blob size
            using (FileStream fs = new FileStream(file, FileMode.Create))//Create empty file.
            {
                fs.SetLength(blobSize);//Set its size
            }
            var blobRequestOptions = new BlobRequestOptions
            {
                RetryPolicy = new ExponentialRetry(TimeSpan.FromSeconds(5), 3),
                MaximumExecutionTime = TimeSpan.FromMinutes(60),
                ServerTimeout = TimeSpan.FromMinutes(60)
            };
            long currentPointer = 0;
            long bytesRemaining = blobSize;
            do
            {
                var bytesToFetch = Math.Min(blockSize, bytesRemaining);
                using (MemoryStream ms = new MemoryStream())
                {
                    //Download range (by default 1 MB)
                    blob.DownloadRangeToStream(ms, currentPointer, bytesToFetch, null, blobRequestOptions);
                    ms.Position = 0;
                    var contents = ms.ToArray();
                    using (var fs = new FileStream(file, FileMode.Open))//Open that file
                    {
                        fs.Position = currentPointer;//Move the cursor to the end of file.
                        fs.Write(contents, 0, contents.Length);//Write the contents to the end of file.
                    }
                    currentPointer += contents.Length;//Update pointer
                    bytesRemaining -= contents.Length;//Update bytes to fetch
                }
            }
            while (bytesRemaining > 0);
        }

J'espère que cela aide.


0 commentaires

-1
votes

Il semble que ce problème soit similaire avec votre autre fil de discussion Impossible de lire readableStreamBody à partir du blob téléchargé .

Voici ma fonction pour vous aider à enregistrer baseLineImage.readableStreamBody dans un fichier, comme ci-dessous.

async function compareToBaseline(imageData, blobName, metadata){

  const baselineBlobName = "MacOSX10.12/chrome/initial"

  const containerURL = ContainerURL.fromServiceURL(serviceURL, "baselines");
  const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, baselineBlobName );
  let baseLineImage = await blockBlobURL.download(aborter, 0);

  await streamToFs('./newest.png', baseLineImage.readableStreamBody)ï¼›
}


0 commentaires

0
votes

blockBlobURL.download () n'a pas de limite de taille de fichier. Mais read () renvoie null ne signifie pas plus de données dans le flux. Vous devez suivre les pratiques de Node.js pour obtenir toutes les données en écoutant l'événement data ou readable .

Par exemple, l'événement data publié par Peter Pan. Ou l'événement lisible publié par les documents officiels de Node.js:

readable.on('readable', () => {
  let chunk;
  while (null !== (chunk = readable.read())) {
    console.log(`Received ${chunk.length} bytes of data.`);
  }
});

Veuillez toujours appeler read () dans un rappel d'événement lisible .


0 commentaires