0

I currently am trying to upload a pdf file of size 260kb with Swagger UI and it doesnt work. If I try to do the same thing with a small 50kb Word file it works.

My controller code is:

    [HttpPost()]
    public async Task<IActionResult> Upload(IFormFile file)
    {
        var name = SanitizeFilename(file.FileName);

        if (String.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException();
        }

        using (Stream stream = file.OpenReadStream())
        {
            await storage.Save(stream, name);
        }
        
        return Accepted();
    }

My AzureBlobStorage class's save method is:

        public async Task<Task> Save(Stream fileStream, string name)
    {
        var blobContainer = await GetBlobContainerAsync();
        CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(name);

        var task = blockBlob.UploadFromStreamAsync(fileStream);

        var success = task.IsCompletedSuccessfully;

        return task;
        //return blockBlob.UploadFromStreamAsync(fileStream);
    }

Here is some of the debug windows:

  1. This is from the controller of the word document:

enter image description here

  1. This is from the controller of the PDF document:

enter image description here

Notice the red/pink lettering which is different.

  1. This is from the AzureBlobStorage save method - word document:

enter image description here

  1. This is from the AzureBlobStorage save method - pdf document:

enter image description here

I have read the IFormFile might not do continuous streaming but how do I know if that is the issue? And if it is, what is the preferred approach?

Mike Lenart
  • 767
  • 1
  • 5
  • 19

1 Answers1

1

I am not following your logic here:

public async Task<Task> Save(Stream fileStream, string name)
{
    var blobContainer = await GetBlobContainerAsync();
    CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(name);

    var task = blockBlob.UploadFromStreamAsync(fileStream);

    var success = task.IsCompletedSuccessfully;

    return task;
    //return blockBlob.UploadFromStreamAsync(fileStream);
}

This is the way it should be written:

public async Task Save(Stream fileStream, string name)
{
    var blobContainer = await GetBlobContainerAsync();
    CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(name);
    await blockBlob.UploadFromStreamAsync(fileStream);
}

You want to await for the task to finish here before you return.

Returning Task<Task> is slightly unorthodox and doesn't make sense for what you want to do here.

Also, keep in mind, if your file is really large, Kestrel server could give up on the request. There is a timeout in the range of around 90 seconds to complete the request. So, if uploading the file takes longer than 90 seconds, the caller could receive an error (but the upload will still finish).

Typically you will dump the file to the disk, then return an Accepted to the caller. Then post the file to a background queue to upload the file. More information about that here.

Andy
  • 12,859
  • 5
  • 41
  • 56