I've been struggling with this for about a day now. I am testing direct to Azure Blob storage upload and getting the dreaded CORS issue. "XMLHttpRequest cannot load https://tempodevelop.blob.core.windows.net/tmp/a4d8e867-f13e-343f-c6d3-a603…Ym0PlrBn%2BU/UzUs7QUhQw%3D&sv=2014-02-14&se=2016-10-12T17%3A59%3A26.638531. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 403."
Things I have already tried:
The code as a whole is available here: https://github.com/mikebz/azureupload
But the relevant parts are here, front end upload:
<script>
/*
* not a true GUID, see here: http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
*/
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
function startUpload() {
var fileName = guid();
jQuery.getJSON("/formfileupload/signature/" + fileName , function(data) {
console.log("got a signature: " + data.bloburl);
uploadFile(data.bloburl, data.signature);
})
.fail(function(jqxhr, textStatus, error) {
console.log( "error: " + textStatus + " - " + error );
})
}
function uploadFile(bloburl, signature) {
var xhr = new XMLHttpRequest();
fileData = document.getElementById('fileToUpload').files[0];
xhr.open("PUT", bloburl + "?" + signature);
xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
xhr.setRequestHeader('x-ms-blob-content-type', fileData.type);
result = xhr.send(fileData);
}
</script>
The signature generation code in python is here:
def generate_access_signature(self, filename):
"""
calls the Azure Web service to generate a temporary access signature.
"""
blob_service = BlobService(
account_name=self.account_name,
account_key=self.account_key
)
expire_at = datetime.utcnow()
expire_at = expire_at + timedelta(seconds = 30)
access_policy = AccessPolicy(permission="rwdl", expiry=expire_at.isoformat())
sas_token = blob_service.generate_shared_access_signature(
container_name="tmp",
blob_name = filename,
shared_access_policy=SharedAccessPolicy(access_policy)
)
return sas_token
According to the error message [The response had HTTP status code 403], it may be the CORS is not enabled for the service or no CORS rules matches the preflight request. Detail Please refer to the Cross-Origin Resource Sharing (CORS) Support for the Azure Storage Services. Or it may be the SAS signature incorrect. Please have a try to troubleshoot
try to check the CORS setting on the Azure Portal under the Blob Service. As there are other services like table, queue, file.
Also Azure explore tools you can use to generate the SAS token
Get the SAS and try to debug it with the generated SAS
Thanks to Tom and Microsoft's support the issue has been resolved.
Solution part #1 - make sure you use the Azure Storage Library for Python version 0.33 or later.
Here is my requirements file:
azure-common==1.1.4
azure-nspkg==1.0.0
azure-storage==0.33.0
cffi==1.8.3
cryptography==1.5.2
dj-database-url==0.4.1
Django==1.10.2
enum34==1.1.6
futures==3.0.5
gunicorn==19.6.0
idna==2.1
ipaddress==1.0.17
pep8==1.7.0
psycopg2==2.6.2
pyasn1==0.1.9
pycparser==2.16
python-dateutil==2.5.3
requests==2.11.1
six==1.10.0
whitenoise==3.2.2
Second issue is generating the signature. The code that generates the right signature is here:
from azure.storage.blob import BlockBlobService, ContainerPermissions
from datetime import datetime, timedelta
class AzureUtils:
def __init__(self, account_name, account_key):
if account_name is None:
raise ValueError("account_name should not be None")
if account_key is None:
raise ValueError("account_key should not be None")
self.account_name = account_name
self.account_key = account_key
def generate_access_signature(self, filename):
"""
calls the Azure Web service to generate a temporary access signature.
"""
block_blob_service = BlockBlobService(
account_name=self.account_name,
account_key=self.account_key
)
expire_at = datetime.utcnow()
expire_at = expire_at + timedelta(seconds=30)
permissions = ContainerPermissions.READ | ContainerPermissions.WRITE | ContainerPermissions.DELETE | ContainerPermissions.LIST
sas_token = block_blob_service.generate_container_shared_access_signature(
"tmp",
permission=permissions,
expiry=expire_at
)
return sas_token
The solution can also be retrieved here: https://github.com/mikebz/azureupload
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With