将文件上载到Azure存储时出错

时间:2011-03-22 20:16:33

标签: azure azure-storage

我正在将标准ASP.NET网站的网站转换为使用Azure。该网站之前已将管理用户上传的Excel文件保存在文件系统中。作为迁移的一部分,我将此文件保存到Azure存储。通过Azure SDK对我的本地存储运行时,它工作正常。 (我使用的是1.3版,因为我不想在开发过程中升级。)

但是,当我将代码指向针对Azure存储本身运行时,该过程通常会失败。我得到的错误是: 发生了System.IO.IOException

  Message=Unable to read data from the transport connection: The connection was closed.
  Source=Microsoft.WindowsAzure.StorageClient
  StackTrace:
       at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.get_Result()
       at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.ExecuteAndWait()
       at Microsoft.WindowsAzure.StorageClient.CloudBlob.UploadFromStream(Stream source, BlobRequestOptions options)
       at Framework.Common.AzureBlobInteraction.UploadToBlob(Stream stream, String BlobContainerName, String fileName, String contentType) in C:\Development\RateSolution2010\Framework.Common\AzureBlobInteraction.cs:line 95
  InnerException: 

代码如下:

public void UploadToBlob(Stream stream, string BlobContainerName, string fileName,
        string contentType)
    {
        // Setup the connection to Windows Azure Storage
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(GetConnStr());

        DiagnosticMonitorConfiguration dmc = DiagnosticMonitor.GetDefaultInitialConfiguration();
        dmc.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
        dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;
        DiagnosticMonitor.Start(storageAccount, dmc);      
        CloudBlobClient BlobClient = null;
        CloudBlobContainer BlobContainer = null;
        BlobClient = storageAccount.CreateCloudBlobClient();

        // For large file copies you need to set up a custom timeout period
        // and using parallel settings appears to spread the copy across multiple threads
        // if you have big bandwidth you can increase the thread number below
        // because Azure accepts blobs broken into blocks in any order of arrival.
        BlobClient.Timeout = new System.TimeSpan(1, 0, 0);
        Role serviceRole = RoleEnvironment.Roles.Where(s => s.Value.Name == "OnlineRates.Web").First().Value;
        BlobClient.ParallelOperationThreadCount = serviceRole.Instances.Count;  

        // Get and create the container
        BlobContainer = BlobClient.GetContainerReference(BlobContainerName);
        BlobContainer.CreateIfNotExist();

        //delete prior version if one exists
        BlobRequestOptions options = new BlobRequestOptions();
        options.DeleteSnapshotsOption = DeleteSnapshotsOption.None;
        CloudBlob blobToDelete = BlobContainer.GetBlobReference(fileName);
        Trace.WriteLine("Blob " + fileName + " deleted to be replaced by newer version.");
        blobToDelete.DeleteIfExists(options);

        //set stream to starting position
        stream.Position = 0;
        long totalBytes = 0;
        //Open the stream and read it back.
        using (stream)
        {
            // Create the Blob and upload the file
            CloudBlockBlob blob = BlobContainer.GetBlockBlobReference(fileName);
            try
            {
                BlobClient.ResponseReceived += new EventHandler<ResponseReceivedEventArgs>((obj, responseReceivedEventArgs)
                =>
                {
                    if (responseReceivedEventArgs.RequestUri.ToString().Contains("comp=block&blockid"))
                    {
                        totalBytes += Int64.Parse(responseReceivedEventArgs.RequestHeaders["Content-Length"]);
                    }
                });                 
                blob.UploadFromStream(stream);
                // Set the metadata into the blob
                blob.Metadata["FileName"] = fileName;
                blob.SetMetadata();
                // Set the properties
                blob.Properties.ContentType = contentType;
                blob.SetProperties();
            }
            catch (Exception exc)
            {
                Logging.ExceptionLogger.LogEx(exc);
            }
         }
     }

我已尝试对代码进行了多种不同的更改:在替换之前删除blob(尽管新blob上也存在问题),设置容器权限,而不是设置权限等。

2 个答案:

答案 0 :(得分:0)

您的代码看起来应该可以使用,但它有许多额外的功能,并不是严格要求的。我会把它降到最低限度并从那里开始。这真的只是一种直觉,但我认为这可能是使用声明给你带来的悲伤。这个enture函数可以写成(假设容器已经存在):

public void UploadToBlob(Stream stream, string BlobContainerName, string fileName,
                string contentType)
            {
                // Setup the connection to Windows Azure Storage
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(GetConnStr());
                CloudBlobClient BlobClient = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer BlobContainer = BlobClient.GetContainerReference(BlobContainerName);
                CloudBlockBlob blob = BlobContainer.GetBlockBlobReference(fileName);
                stream.Position = 0;
                blob.UploadFromStream(stream);
            }

关于我删除的内容的说明:

  • 您应该在app启动时设置一次诊断,而不是每次调用方法时都设置诊断。通常在RoleEntryPoint.OnStart()
  • 如果您有更多实例,我不确定您为什么要尝试将ParallelOperationThreadCount设置得更高。这两件事似乎无关。
  • 每次保存容器/表时,检查容器/表是否存在都不是好的形式。在应用程序启动时进行一次检查或在网站外部进行检查以确保存在所有必需的容器/表/队列,这种情况更为常见。当然,如果您尝试动态创建容器,则不然。

答案 1 :(得分:0)

问题原来是笔记本电脑上的防火墙设置。这是我最初在家中设置的个人笔记本电脑,因此没有为企业环境设置防火墙规则,导致上传和下载的性能降低。