Reputation: 2065
I followed this great article by Gaurav Mantri in order to upload files using HTML5/Javascript directly into blob storage.
However I am finding that during the upload portion this portion of his code fails with the 403 error.
And the funny thing is, this happens randomly. Sometimes the upload actually works and everything completes successfully however majority of the time it is failing with the 403 error.
One thing to note: I am hoping that CORS support will be added soon to Azure however for time being I am using Chrome (with the chrome.exe --disable-web-security option) to get around the issue.
PUT https://mystorage.blob.core.windows.net/asset-38569007-3316-4350…Giv17ye4bocVWDbA/EQ+riNiG3wEGrFucbd1BKI9E=&comp=block&blockid=YmxvY2stMA==
403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)
$.ajax({
url: uri,
type: "PUT",
data: requestData,
processData: false,
beforeSend: function(xhr) {
xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
xhr.setRequestHeader('Content-Length', requestData.length);
},
success: function (data, status) {
console.log(data);
console.log(status);
bytesUploaded += requestData.length;
var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
$("#fileUploadProgress").text(percentComplete + " %");
uploadFileInBlocks();
},
error: function(xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
I have put a 30-sec delay after creating the asset/locator/file in Azure before actually starting the upload portion in order to give time for the Locator to be propagated.
Any suggestion to what I could be missing?
Upvotes: 3
Views: 1056
Reputation: 2065
Many thanks to Gaurav for pointing me in the direction of the issue.
It turns out that I was making JSON calls to the server which would create the assets/locators/policies and then return the upload uri back.
However my upload uri was of type Uri and when JSON serialized it, it didn't properly encode it.
After changing my uri object (on the server) to a string (and calling uploaduri = (new UriBuilder(theuri)).ToString(); ) the uri returned back to the web client was properly encoded and I no longer got the 403 errors.
So as a heads up to others, if you get this same issue, you may want to look at the encoding of your upload uri.
Upvotes: 2
Reputation: 2065
Gaurav here's the code I use to create the empty asset (w/ locator and file):
/// <summary>
/// Creates an empty asset on Azure and prepares it to upload
/// </summary>
public FileModel Create(FileModel file)
{
// Update the file model with file and asset id
file.FileId = Guid.NewGuid().ToString();
// Create the new asset
var createdAsset = this.Context.Assets.Create(file.AssetName.ToString(), AssetCreationOptions.None);
// Create the file inside the asset and set its size
var createdFile = createdAsset.AssetFiles.Create(file.Filename);
createdFile.ContentFileSize = file.Size;
// Create a policy to allow uploading to this asset
var writePolicy = this.Context.AccessPolicies.Create("Policy For Copying", TimeSpan.FromDays(365 * 10), AccessPermissions.Read | AccessPermissions.Write | AccessPermissions.List);
// Get the upload locator
var destinationLocator = this.Context.Locators.CreateSasLocator(createdAsset, writePolicy);
// Get the SAS Uri and save it to file
var uri = new UriBuilder(new Uri(destinationLocator.Path));
uri.Path += "/" + file.Filename;
file.UploadUri = uri.Uri;
// Return the updated file
return file;
}
Upvotes: 0