簡體   English   中英

Azure Blob上載無法在ASP .Net Core Application中使用

[英]Azure Blob Upload not working in ASP .Net Core Application

我正在嘗試將文件上傳到Asp .Net Core中的Azure blob存儲。 一切似乎都在工作,但沒有上傳文件。 這是我的代碼片段:

        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();

發生了什么?

調試器逐步執行result.GetAwaiter().GetResult() ,不會發生異常。 GetResult()調用之后檢查result任務變量顯示任務狀態為RanToCompletion且異常屬性為空。 我的blob容器在早期代碼中成功創建,表明與blob存儲的連接成功。 GetResult()立即完成,所以似乎沒有任何事情發生。

我檢查過的事情

  • rawData是一個填充了文件數據的MemoryStream 使用注釋行嘗試通過流上傳也不成功。
  • 與Azure的連接正常。
  • 文件路徑存在。
  • 沒有例外。
  • 我的調試窗口輸出中唯一的東西是Started Thread <ThreadNumber>
  • 在對blobReference.UploadFromFileAsync()的調用中放置無效路徑會按預期引發FileNotFoundException
  • 我嘗試從netcoreapp2.1將我的項目降級到netcoreapp2.0 netcoreapp2.1沒有成功。

以下代碼與WindowsAzure.Storage - 版本9.3.1包適用於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>();

我在該方法中實現的接口是沒有異步簽名的更大生態系統的一部分。 重構它需要付出很多努力。

您可以使用Wait()替換await以實現異步簽名。請參閱以下代碼:

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();
}

在Blob名稱中添加/前綴會導致靜默失敗。 該文件根本不上傳。 刪除/前綴修復了問題。

使用.NET Core 2.1和WindowsAzure.Storage 9.3.2,所有方法現在都是異步的。 如果不等待所有異步方法調用,則可能會出現靜默失敗。 這個問題下面的評論幫我解決了這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM