Reputation: 4119
I am trying to upload a file to Azure blob storage in Asp .Net Core. Everything seems to be working but no file is uploaded. Here is my code snippet:
var blobReference = GetBlobReference();
rawData.Position = 0;
// var result = blobReference.UploadFromStreamAsync(rawData);
var result = blobReference.UploadFromFileAsync("C:\\users\\tjaartb\\Downloads\\DebitOrderMandate.pdf");
result.GetAwaiter().GetResult();
var blobPath = blobReference.Uri.ToString();
The debugger steps over the result.GetAwaiter().GetResult()
with no exceptions occurring. Checking the result
Task variable after the GetResult()
call shows that the task state is RanToCompletion
and the exception property is blank. My blob container is created successfully in earlier code indicating that the connection to blob storage is successful. GetResult()
finishes instantly, so it seems like nothing is happening.
rawData
is a MemoryStream
that is populated with file data. Using the commented line to try and upload via a stream is not successful either.Started Thread <ThreadNumber>
blobReference.UploadFromFileAsync()
throws a FileNotFoundException
as expected.netcoreapp2.0
from netcoreapp2.1
with no success.Upvotes: 3
Views: 3384
Reputation: 51
blob.UploadFromStreamAsync(fileStream).Wait();
This method uploads the content of a stream (fileStream) to a blob asynchronously, and .Wait() is used to block the thread until the upload completes
Upvotes: 1
Reputation: 4074
With .NET Core 2.1 and WindowsAzure.Storage 9.3.2 all the methods are now async. If you don't await all the async method calls you can get silent failures. The comments below the question helped me figure that out.
Upvotes: 0
Reputation: 21
the following code with WindowsAzure.Storage - Version 9.3.1 package works on Asp Net Core 2.1.
public class AzureBlobModel
{
public string FileName { get; set; }
public long? FileSize { get; set; }
public Stream Stream { get; set; }
public string ContentType { get; set; }
}
public interface IImageStore
{
Task<string> SaveDocument(Stream documentStream);
Task<bool> DeleteDocument(string imageId);
Task<AzureBlobModel> DownloadDocument(string documentId, string fileName);
string UriFor(string documentId);
}
public class ImageStore : IImageStore
{
CloudBlobClient blobClient;
string baseUri = "https://xxxxx.blob.core.windows.net/";
public ImageStore()
{
var credentials = new StorageCredentials("xxxxx accountName xxxxx", "xxxxx keyValue xxxxx");
blobClient = new CloudBlobClient(new Uri(baseUri), credentials);
}
public async Task<string> SaveDocument(Stream documentStream)
{
var documentId = Guid.NewGuid().ToString();
var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);
await blob.UploadFromStreamAsync(documentStream);
return documentId;
}
public async Task<bool> DeleteDocument(string documentId)
{
var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);
bool blobExisted = await blob.DeleteIfExistsAsync();
return blobExisted;
}
public async Task<AzureBlobModel> DownloadDocument(string documentId, string fileName)
{
var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);
var doc = new AzureBlobModel()
{
FileName = fileName,
Stream = new MemoryStream(),
};
doc.Stream = await blob.OpenReadAsync();
doc.ContentType = blob.Properties.ContentType;
doc.FileSize = blob.Properties.Length;
return doc;
}
public string UriFor(string documentId)
{
var sasPolicy = new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-15),
SharedAccessExpiryTime = DateTime.UtcNow.AddDays(1)
};
var container = blobClient.GetContainerReference("xxxxx container xxxxx");
var blob = container.GetBlockBlobReference(documentId);
var sas = blob.GetSharedAccessSignature(sasPolicy);
return $"{baseUri}xxxxx container xxxxx/{documentId}{sas}";
}
}
public class DocForCreationDto
{
public IFormFile File { get; set; }
// other properties ...
}
// On the controller
[HttpPost]
public async Task<IActionResult> Upload([FromForm]DocForCreationDto docForCreationDto)
{
if (docForCreationDto.File == null || !ModelState.IsValid)
{
return new UnprocessableEntityObjectResult(ModelState);
}
string documentId = string.Empty;
using (var stream = docForCreationDto.File.OpenReadStream())
{
documentId = await _imageStore.SaveDocument(stream);
}
if (documentId != string.Empty)
{
// upload ok ...
//some business logic here ...
return Ok();
}
return BadRequest("xxx error xxx");
}
[HttpGet("{documentId}", Name = "GetDocument")]
public async Task<IActionResult> GetDocument(int documentId)
{
var doc = await _imageStore.DownloadDocument(documentId, "output filename");
return File(doc.Stream, doc.ContentType, doc.FileName);
}
// On Startup - ConfigureServices
services.AddSingleton<IImageStore, ImageStore>();
Upvotes: 2
Reputation: 4119
Adding a /
prefix to a Blob name results in a silent failure. The file does not upload at all. removing the /
prefix fixed the problem.
Upvotes: 0
Reputation: 20067
The interface I am implementing in that method is part of a larger ecosystem that doesn't have async signatures. It would require a lot of effort to refactor it.
You could use Wait()
to replace await
to implement the async signatures.Refer to the following code:
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connection);
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
var cloudBlobContainer = cloudBlobClient.GetContainerReference("containername");
CloudBlockBlob blob = cloudBlobContainer.GetBlockBlobReference("DebitOrderMandate.pdf");
using (var fileStream = System.IO.File.OpenRead("C:\\users\\tjaartb\\Downloads\\DebitOrderMandate.pdf"))
{
blob.UploadFromStreamAsync(fileStream).Wait();
}
Upvotes: 0