【问题标题】:NotFound Exception in Azure BlobStorage在 Azure Blob 存储中未找到异常
【发布时间】:2015-04-29 10:21:37
【问题描述】:

我知道这个问题已经被问过很多次了。但我根本无法让它可靠地工作。

我得到了这个例外:

Microsoft.WindowsAzure.Storage.StorageException was unhandled by user code
  HResult=-2146233088 Message=The remote server returned an error: NotFound.
  Source=Microsoft.WindowsAzure.Storage StackTrace: at Microsoft.WindowsAzure.Storage.Core.Util.StorageAsyncResult\`1.End()
       at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.EndUploadFromStream(IAsyncResult asyncResult) at Microsoft.WindowsAzure.Storage.Core.Util.AsyncExtensions.<>c__DisplayClass4.<CreateCallbackVoid>b__3(IAsyncResult ar)

--- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
       at MVVMTestApp.View.ShieldCreator.<OnNavigatedFrom>d__7.MoveNext()
  InnerException: System.Net.WebException
       HResult=-2146233079
       Message=The remote server returned an error: NotFound.
       Source=Microsoft.WindowsAzure.Storage
       StackTrace:
            at Microsoft.WindowsAzure.Storage.Shared.Protocol.HttpResponseParsers.ProcessExpectedStatusCodeNoException[T](HttpStatusCode expectedStatusCode, HttpStatusCode actualStatusCode, T retVal, StorageCommandBase\`1 cmd, Exception ex)
            at Microsoft.WindowsAzure.Storage.Shared.Protocol.HttpResponseParsers.ProcessExpectedStatusCodeNoException[T](HttpStatusCode expectedStatusCode, HttpWebResponse resp, T retVal, StorageCommandBase\`1 cmd, Exception ex)
            at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.<>c__DisplayClass39.<PutBlobImpl>b__38(RESTCommand`1 cmd, HttpWebResponse resp, Exception ex, OperationContext ctx)
            at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.EndGetResponse[T](IAsyncResult getResponseResult)
       InnerException: System.Net.WebException
            HResult=-2146233079
            Message=The remote server returned an error: NotFound.
            Source=System.Windows
            StackTrace:
                 at System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
                 at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClasse.<EndGetResponse>b__d(Object sendState)
                 at System.Net.Browser.AsyncHelper.<>c__DisplayClass1.<BeginOnUI>b__0(Object sendState)
            InnerException: 

我用来上传到服务器的代码是:

 MemoryStream stream = new MemoryStream();
        if (bi != null)
        {
            WriteableBitmap bmp = new WriteableBitmap((BitmapSource)bi);
            bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
        }
        stream.Seek(0, SeekOrigin.Begin);
        DTO.PictureStorage uploadImage = new DTO.PictureStorage();
        uploadImage.UserId = App.UserInformationID;
        uploadImage.ContainerName = ("crestimage" + App.UserInformationID.Replace(":", "")).ToLower();
        uploadImage.ResourceName = Guid.NewGuid().ToString().ToLower() + ".jpg";

        var resultPicture = await App.MobileService.InvokeApiAsync<DTO.PictureStorage, DTO.PictureStorage>("user/blobStorage", uploadImage);
        uploadImage = resultPicture;
        // If we have a returned SAS, then upload the blob.
        if (!string.IsNullOrEmpty(uploadImage.SasQueryString))
        {
            // Get the URI generated that contains the SAS 
            // and extract the storage credentials.
            StorageCredentials cred = new StorageCredentials(uploadImage.SasQueryString);
            var imageUri = new Uri(uploadImage.ImageUri);

            // Instantiate a Blob store container based on the info in the returned item.
            CloudBlobContainer container = new CloudBlobContainer(
                new Uri(string.Format("http://{0}/{1}",
                    imageUri.Host.ToLower(), uploadImage.ContainerName.ToLower())), cred);

            // Upload the new image as a BLOB from the stream.
            CloudBlockBlob blobFromSASCredential =
                container.GetBlockBlobReference(uploadImage.ResourceName);
            await blobFromSASCredential.UploadFromStreamAsync(stream);  //The exception is thrown here

            // When you request an SAS at the container-level instead of the blob-level,
            // you are able to upload multiple streams using the same container credentials.

            stream = null;
        }

在服务器上我有这个代码:

 string storageAccountName;
                string storageAccountKey;

                // Try to get the Azure storage account token from app settings.  
                if (!(Services.Settings.TryGetValue("STORAGE_ACCOUNT_NAME", out storageAccountName) |
                Services.Settings.TryGetValue("STORAGE_ACCOUNT_ACCESS_KEY", out storageAccountKey)))
                {
                    Services.Log.Error("Could not retrieve storage account settings.");
                }

                // Set the URI for the Blob Storage service.
                Uri blobEndpoint = new Uri(string.Format("https://{0}.blob.core.windows.net", storageAccountName));

                // Create the BLOB service client.
                CloudBlobClient blobClient = new CloudBlobClient(blobEndpoint,
                    new StorageCredentials(storageAccountName, storageAccountKey));

                if (item.ContainerName != null)
                {
                    // Set the BLOB store container name on the item, which must be lowercase.
                    item.ContainerName = item.ContainerName.ToLower();

                    // Create a container, if it doesn't already exist.
                    CloudBlobContainer container = blobClient.GetContainerReference(item.ContainerName);

                    try
                    {
                        await container.DeleteIfExistsAsync();
                        Services.Log.Info("Deleted.");
                    }
                    catch 
                    {
                        Services.Log.Info("Could not DeleteIfExist.");
                    }
                    await container.CreateIfNotExistsAsync();

                    // Create a shared access permission policy. 
                    BlobContainerPermissions containerPermissions = new BlobContainerPermissions();

                    // Enable anonymous read access to BLOBs.
                    containerPermissions.PublicAccess = BlobContainerPublicAccessType.Blob;
                    container.SetPermissions(containerPermissions);

                    // Define a policy that gives write access to the container for 5 minutes.                                   
                    SharedAccessBlobPolicy sasPolicy = new SharedAccessBlobPolicy()
                    {
                        SharedAccessStartTime = DateTime.UtcNow,
                        SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(5),
                        Permissions = SharedAccessBlobPermissions.Write
                    };

                    // Get the SAS as a string.
                    item.SasQueryString = container.GetSharedAccessSignature(sasPolicy);

                    // Set the URL used to store the image.
                    item.ImageUri = string.Format("{0}{1}/{2}", blobEndpoint.ToString(),
                        item.ContainerName, item.ResourceName);
                }

                // Complete the insert operation.
                user.ContainerName = item.ContainerName;
                user.ResourceName = item.ResourceName;
                user.SasQueryString = item.SasQueryString;
                user.ImageUri = item.ImageUri;
                user.Update = DateTime.UtcNow.AddMinutes(5);

                db.SaveChanges();

我根据这个答案介绍了删除等待:https://stackoverflow.com/a/3221638/2076775

希望有人能告诉我我犯了什么愚蠢的错误,因为我找不到它。不幸的是,我无法让提琴手工作(公司政策和代理设置:S)。

代码的目的是上传图片,如果用户更改图片,应该可以一次又一次地上传到同一个地址。

【问题讨论】:

  • 什么操作返回 404?
  • 对不起应该已经指定了:CloudBlockBlob blobFromSASCredential = container.GetBlockBlobReference(uploadImage.ResourceName); await blobFromSASCredential.UploadFromStreamAsync(stream);我现在已经在代码中标记了

标签: c# azure azure-blob-storage


【解决方案1】:

您的服务器代码使用当前时间作为 SAS 开始时间,这可能会由于时钟偏差而导致身份验证问题。换言之,如果 Blob 服务的当前时间晚于您服务器的当前时间,那么 SAS 令牌此时将无效。如果您对开始时间没有硬性限制,建议您完全省略它。

【讨论】:

  • 好的,我有客户想要创建/更新它的开始时间。我认为通过使用 UTC,您会限制并关闭以消除问题?所以你会删除这些行SharedAccessStartTime = DateTime.UtcNow, SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(5)?
  • 您应该只删除开始时间,因为无论如何设置为现在都不会增加太多价值。
  • 好的,等我在电脑上的时候再试试。这是唯一的问题吗?如果是这样,MSDN 上的教程中不应该提到这一点吗?感谢您的宝贵时间。
  • 我看了看时间,已经休息了几个小时。所以谢谢!
猜你喜欢
  • 1970-01-01
  • 2022-08-24
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 2019-08-17
  • 2018-02-17
  • 2019-07-24
  • 2017-12-14
相关资源
最近更新 更多