C # Azure file upload error The specified blob or block content is not valid

I upload files to azure storage.

public class AzureBlob : ICloudBlob
{
    private string _fileName;
    public string FileName
    {
        get => _fileName;
        set
        {
            _fileName = value;
            _cloudBlockBlob = CloudBlobContainer.GetBlockBlobReference(value);
        }
    }
    public CloudBlobContainer CloudBlobContainer { get; set; }
    private CloudBlockBlob _cloudBlockBlob;

    public async Task UploadChunksFromPathAsync(string path, long fileLength)
    {
        const int blockSize = 256 * 1024;
        var bytesToUpload = fileLength;
        long bytesUploaded = 0;
        long startPosition = 0;

        var blockIds = new List<string>();
        var index = 0;

        do
        {
            var bytesToRead = Math.Min(blockSize, bytesToUpload);
            var blobContents = new byte[bytesToRead];

            using (var fs = new FileStream(path, FileMode.Open))
            {
                fs.Position = startPosition;
                fs.Read(blobContents, 0, (int) bytesToRead);
            }

            var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString("d6")));

            blockIds.Add(blockId);
            await _cloudBlockBlob.PutBlockAsync(blockId, new MemoryStream(blobContents), null);

            bytesUploaded += bytesToRead;
            bytesToUpload -= bytesToRead;
            startPosition += bytesToRead;
            index++;
        } while (bytesToUpload > 0);

        await _cloudBlockBlob.PutBlockListAsync(blockIds);   
    }
}

      

This is great for single file upload, multiple file uploads calling this method one after the other throw 400 error on _cloudBlockBlob.PutBlockListAsync

with azure error

The specified blob or block content is not valid.

If I remove the wait keyword in _cloudBlockBlob.PutBlockListAsync

, it works fine.

Blocking of the same length. What am I doing wrong?

Edit

Call code in controller:

[HttpPost]
public async Task<IActionResult> Upload([FromBody] UploadViewModel model)
{
    var audioBlob = _cloudStorage.GetBlob(CloudStorageType.Audio, model.AudioName);

    await audioBlob.UploadChunksFromPathAsync(model.AudioPath, model.FileLength);

    return Ok();
}

      

storage:

public enum CloudStorageType
{
    Audio,
    Image,
}

public class AzureStorage : ICloudStorage
{
    public IDictionary<CloudStorageType, ICloudBlob> CloudBlobs { get; set; }

    public AzureStorage(IConfiguration configuration)
    {
        var storageAccount = CloudStorageAccount.Parse(configuration["ConnectionStrings:StorageConnectionString"]);
        var blobClient = storageAccount.CreateCloudBlobClient();

        CloudBlobs = new Dictionary<CloudStorageType, ICloudBlob>();

        foreach (CloudStorageType cloudStorageType in Enum.GetValues(typeof(CloudStorageType)))
        {
            CloudBlobs[cloudStorageType] = new AzureBlob(cloudStorageType.ToString().ToLower(), blobClient);
        }
    }

    public ICloudBlob GetBlob(CloudStorageType cloudStorageType, string fileName)
    {
        CloudBlobs[cloudStorageType].FileName = fileName;

        return CloudBlobs[cloudStorageType];
    }
}

      

Startup.cs

var azureStorage = new AzureStorage(_configuration);

// Add application services.
services.AddSingleton(_configuration);
services.AddSingleton<ICloudStorage>(azureStorage);

      

+3


source to share


1 answer


Edit: The reason was that halfway through the download path the blob was overwritten by the following file. Basically create a new frame, each one loading, so it doesn't.

Found it out. The first download will work fine, however the second download will throw an error if the previous download has not finished yet, since this block has already been used to download other blocks.



Fixed creating a new blockblock for every download, not just using it.

public async Task UploadChunksFromPathAsync(string path, long fileLength)
{
    var cloudBlockBlob = CloudBlobContainer.GetBlockBlobReference(FileName);

    const int blockSize = 256 * 1024;
    var bytesToUpload = fileLength;
    long bytesUploaded = 0;
    long startPosition = 0;

    var blockIds = new List<string>();
    var index = 0;

    do
    {
        var bytesToRead = Math.Min(blockSize, bytesToUpload);
        var blobContents = new byte[bytesToRead];

        using (var fs = new FileStream(path, FileMode.Open))
        {
            fs.Position = startPosition;
            fs.Read(blobContents, 0, (int) bytesToRead);
        }

        var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString("d6")));

        blockIds.Add(blockId);
        await cloudBlockBlob.PutBlockAsync(blockId, new MemoryStream(blobContents), null);

        bytesUploaded += bytesToRead;
        bytesToUpload -= bytesToRead;
        startPosition += bytesToRead;
        index++;
    } while (bytesToUpload > 0);

    await cloudBlockBlob.PutBlockListAsync(blockIds);   
}

      

+3


source







All Articles