Azure Blob 存储中未找到异常

NotFound Exception in Azure BlobStorage

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

我得到这个异常:

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

我根据这个答案介绍了delete await:

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

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

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