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 令牌此时将无效。如果您对开始时间没有硬性限制,建议您完全省略。
我知道这个问题已经被问过很多次了。但我就是无法让它可靠地工作。
我得到这个异常:
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 令牌此时将无效。如果您对开始时间没有硬性限制,建议您完全省略。