简体   繁体   English

Azure 云存储 SDK UploadFromStreamAsync 不起作用

[英]Azure Cloud storage SDK UploadFromStreamAsync not working

I am trying to upload files to Azure blob storage in .Net Core 2.1.我正在尝试将文件上传到 .Net Core 2.1 中的 Azure blob 存储。 Below is my code.下面是我的代码。

IFormFileCollection files = formCollection.Files;

foreach (var file in files)
{
    if (file.Length > 0)
    {
        _azureCloudStorage.UploadContent(cloudBlobContainer, file.OpenReadStream(), file.FileName);
    }
}

UploadContent implementation- UploadContent实现-

public async void UploadContent(CloudBlobContainer containerReference, Stream contentStream, string blobName)
{
    try
    {
        using (contentStream)
        {
            var blockBlobRef = containerReference.GetBlockBlobReference(blobName);
            //await containerReference.SetPermissionsAsync(new BlobContainerPermissions
            //{
            //    PublicAccess = BlobContainerPublicAccessType.Blob
            //});
            await blockBlobRef.UploadFromStreamAsync(contentStream);
        }
    }
    catch(Exception ex)
    {
        //Error here
    }
}

The code executes with below error-代码执行时出现以下错误-

{System.ObjectDisposedException: Cannot access a closed file. {System.ObjectDisposedException:无法访问已关闭的文件。 at System.IO.FileStream.get_Position() at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.get_Position() at Microsoft.AspNetCore.Http.Internal.ReferenceReadStream.VerifyPosition() at Microsoft.AspNetCore.Http.Internal.ReferenceReadStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at Microsoft.WindowsAzure.Storage.Core.Util.StreamExtensions.WriteToAsync[T](Stream stream, Stream toStream, IBufferManager bufferManager, Nullable 1 copyLength, Nullable 1 maxLength, Boolean calculateMd5, ExecutionState 1 executionState, StreamDescriptor streamCopyState, CancellationToken token) in C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\Common\\Core\\Util\\StreamExtensions.cs:line 301 at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream source, Nullable 1 length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, IProgress 1 progressHandler, CancellationToken cancellationToken) in C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs:line 352 at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream source, Nullable在 System.IO.FileStream.get_Position() 在 Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.get_Position() 在 Microsoft.AspNetCore.Http.Internal.ReferenceReadStream.VerifyPosition() 在 Microsoft.AspNetCore.Http.Internal.ReferenceReadStream.ReadAsync(Byte [] 缓冲区,Int32 偏移量,Int32 计数,CancellationToken 取消令牌)在 Microsoft.WindowsAzure.Storage.Core.Util.StreamExtensions.WriteToAsync[T](流流,流到流,IBufferManager bufferManager,Nullable 1 copyLength, Nullable 1 maxLength,Boolean calculateMd5 , ExecutionState 1 executionState, StreamDescriptor streamCopyState, CancellationToken token) in C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\Common\\Core\\Util\\StreamExtensions.cs:line 301 at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream source, Nullable 1 长度,AccessCondition accessCondition,BlobRequestOptions 选项,OperationContext operationContext,IProgress 1 progressHandler, CancellationToken cancellationToken) in C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs:line 352 at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream source, Nullable 1 progressHandler, CancellationToken cancellationToken) in C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs:line 352 at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream source, Nullable 1 length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) in C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs:line 290 at Common.AzureCloudStorage.UploadContent(CloudBlobContainer containerReference, Stream contentStream, String blobName) 1 progressHandler, CancellationToken cancellationToken) in C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs:line 352 at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream source, Nullable 1 长度、AccessCondition accessCondition、BlobRequestOptions 选项、OperationContext operationContext、CancellationToken CancellationToken)在 C:\\Program Files (x86)\\Jenkins\\workspace\\release_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs: 在 Common.AzureCloudStorage.UploadContent(CloudBlobContainer containerReference) 的第 290 行, 流内容流, 字符串 blobName)

Alternate solution which worked for me: adding to azure blob storage with stream对我有用的替代解决方案: 使用流添加到 azure blob 存储

Any help with this please?请问有什么帮助吗? Please let me know if I can provide more details.如果我能提供更多详细信息,请告诉我。

My solution was to wait until the task had completed before continuing, eg我的解决方案是等到任务完成后再继续,例如

    private async void SaveAsync(IFormFile file)
    {
        CloudBlockBlob blob = this.blobContainer.GetBlockBlobReference(file.FileName);
        var task = blob.UploadFromStreamAsync(file.OpenReadStream(), file.Length);

        while (task.IsCompleted == false) {
            Thread.Sleep(1000);
        }

    }

Maybe passing in the length helped as well?也许传递长度也有帮助?

My solution was to include the file length and set the position = 0.我的解决方案是包含文件长度并设置位置 = 0。

MemoryStream outStr = new MemoryStream();
CloudBlockBlob myBlob = container.GetBlockBlobReference(name);
outStr.Position = 0;
await myBlob.UploadFromStreamAsync(outStr, outStr.Length);

Same problem, few years later (WindowsAzure.Storage version 3.0.3.0, targetFramework net45).同样的问题,几年后(WindowsAzure.Storage 版本 3.0.3.0,targetFramework net45)。
Synchonous UploadFromStream works, UploadFromStreamAsync does not.同步UploadFromStream有效, UploadFromStreamAsync无效。 I would vote up to suspect Azure SDK does'nt hone async versions, rather than sdk usage deficiency.我会投票怀疑 Azure SDK 不会磨练异步版本,而不是 sdk 使用不足。 And, I am also a fairly experienced developer - too experienced to stumble now and then over a Microsoft feature which is declared, but doesn't work when scrutinized closer.而且,我也是一名相当有经验的开发人员 - 经验丰富,不会时不时地被一个 Microsoft 功能所迷惑,该功能已声明,但在仔细审查时却不起作用。
The same here for other async methods (eg SetPropertiesAsync ).其他异步方法(例如SetPropertiesAsync )也是如此。 I've been debugging my method (below), and was just losing the breakpoint after every * Async method - that's how I've figured this out.我一直在调试我的方法(如下),并且在每个 * Async方法之后都丢失了断点 - 这就是我想出来的。 And out of curiousity changed the UploadFromStreamAsync => UploadFromStream , and then SetPropertiesAsync to just SetProperties .出于好奇,将UploadFromStreamAsync => UploadFromStreamSetPropertiesAsync更改为仅SetProperties

    public async Task StoreItem(string filename, MemoryStream content, string contentType, ICloudBlob cloudBlob)
{
    cloudBlob.UploadFromStream(content); //this line works
    //await cloudBlob.UploadFromStreamAsync(content); //doesn't work
    cloudBlob.Properties.ContentType = contentType;
    cloudBlob.SetProperties();
    //await cloudBlob.SetPropertiesAsync(); //doesn't work either
}

Setting the position to 0 and passing stream length to UploadFromStreamAsync() solved my issue (file was not getting uploaded, even if the container existed already).将位置设置为 0 并将流长度传递给 UploadFromStreamAsync() 解决了我的问题(文件没有被上传,即使容器已经存在)。

using (var stream = file.OpenReadStream())
{
    var fileBlob = container.GetBlockBlobReference(fileName);
    stream.Position = 0;
    fileBlob.UploadFromStreamAsync(stream, stream.Length);
}

I have tested your method UploadContent , it worked fine.我已经测试了您的方法UploadContent ,它运行良好。

I guess your problem may be the file collection you got.我想你的问题可能是你得到的文件集合。

Here is my code for your reference:这是我的代码供您参考:

using ConsoleAppCore.DAL;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using System;
using System.IO;

namespace ConsoleAppCore
{
    class Program
    {
        static void Main(string[] args)
        {
            Run();
            Console.WriteLine("Success");
            Console.ReadLine();
        }

        public static void Run()
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=xxxxx;AccountKey=O7xB6ebGq8e86XQSy2vkvSi/x/exxxxxxxxxxkly1DsQPYY5dF2JrAVHtBozbJo29ZrrGJA==;BlobEndpoint=https://xxxx.blob.core.windows.net/;QueueEndpoint=https://xxxx.queue.core.windows.net/;TableEndpoint=https://xxxx.table.core.windows.net/;FileEndpoint=https://xxxx.file.core.windows.net/;");

            CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer container = cloudBlobClient.GetContainerReference("containertest");

            container.CreateIfNotExists();
            DirectoryInfo dir = new DirectoryInfo("E://Test");

            foreach (FileInfo file in dir.GetFiles())
            {

                BlobStorage.UploadContent(container, file.OpenRead(), file.Name);

            }
        }


    }
}

And the UploadContent method in my BlobStorage class:我的BlobStorage类中的UploadContent方法:

using Microsoft.Azure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace ConsoleAppCore.DAL
{
    public class BlobStorage
    {
        public static async void UploadContent(CloudBlobContainer containerReference, Stream contentStream, string blobName)
        {
            try
            {
                using (contentStream)
                {

                    var blockBlobRef = containerReference.GetBlockBlobReference(blobName);
                    //await containerReference.SetPermissionsAsync(new BlobContainerPermissions
                    //{
                    //    PublicAccess = BlobContainerPublicAccessType.Blob
                    //});
                    await blockBlobRef.UploadFromStreamAsync(contentStream);
                }
            }
            catch (Exception ex)
            {
                //Error here
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM