amazon web services - How to set content-length-range for s3 browser upload via boto -


the issue

i'm trying upload images directly s3 browser , getting stuck applying content-length-range permission via boto's s3connection.generate_url method.

there's plenty of information signing post forms, setting policies in general , heroku method doing similar submission. can't figure out life of me how add "content-length-range" signed url.

with boto's generate_url method (example below), can specify policy headers , have got working normal uploads. can't seem add policy restriction on max file size.

server signing code

## django request handler  boto.s3.connection import s3connection django.conf import settings django.http import httpresponse import mimetypes import json  conn = s3connection(settings.s3_access_key, settings.s3_secret_key) object_name = request.get['objectname'] content_type = mimetypes.guess_type(object_name)[0]  signed_url = conn.generate_url(     expires_in = 300,      method = "put",      bucket = settings.bucket_name,      key = object_name,     headers = {'content-type': content_type, 'x-amz-acl':'public-read'})  return httpresponse(json.dumps({'signedurl': signed_url})) 

on client, i'm using reacts3uploader based on tadruj's s3upload.js script. shouldn't affecting seems pass along whatever signedurls covers, copied below simplicity.

reacts3uploader js code (simplified)

uploadfile: function() {     new s3upload({         fileelement: this.getdomnode(),         signingurl: /api/get_signing_url/,         onprogress: this.props.onprogress,         onfinishs3put: this.props.onfinish,         onerror: this.props.onerror     }); },  render: function() {     return this.transferpropsto(         react.dom.input({type: 'file', onchange: this.uploadfile})     ); } 

s3upload.js

s3upload.prototype.signingurl = '/sign-s3'; s3upload.prototype.fileelement = null;  s3upload.prototype.onfinishs3put = function(signresult) {     return console.log('base.onfinishs3put()', signresult.publicurl); };  s3upload.prototype.onprogress = function(percent, status) {     return console.log('base.onprogress()', percent, status); };  s3upload.prototype.onerror = function(status) {     return console.log('base.onerror()', status); };  function s3upload(options) {     if (options == null) {         options = {};     }     (option in options) {         if (options.hasownproperty(option)) {             this[option] = options[option];         }     }     this.handlefileselect(this.fileelement); }  s3upload.prototype.handlefileselect = function(fileelement) {     this.onprogress(0, 'upload started.');     var files = fileelement.files;     var result = [];     (var i=0; < files.length; i++) {         var f = files[i];         result.push(this.uploadfile(f));     }     return result; };  s3upload.prototype.createcorsrequest = function(method, url) {     var xhr = new xmlhttprequest();      if (xhr.withcredentials != null) {         xhr.open(method, url, true);     }     else if (typeof xdomainrequest !== "undefined") {         xhr = new xdomainrequest();         xhr.open(method, url);     }     else {         xhr = null;     }     return xhr; };  s3upload.prototype.executeonsignedurl = function(file, callback) {     var xhr = new xmlhttprequest();     xhr.open('get', this.signingurl + '&objectname=' + file.name, true);     xhr.overridemimetype && xhr.overridemimetype('text/plain; charset=x-user-defined');     xhr.onreadystatechange = function() {         if (xhr.readystate === 4 && xhr.status === 200) {             var result;             try {                 result = json.parse(xhr.responsetext);             } catch (error) {                 this.onerror('invalid signing server response json: ' + xhr.responsetext);                 return false;             }             return callback(result);         } else if (xhr.readystate === 4 && xhr.status !== 200) {             return this.onerror('could not contact request signing server. status = ' + xhr.status);         }     }.bind(this);     return xhr.send(); };  s3upload.prototype.uploadtos3 = function(file, signresult) {     var xhr = this.createcorsrequest('put', signresult.signedurl);     if (!xhr) {         this.onerror('cors not supported');     } else {         xhr.onload = function() {             if (xhr.status === 200) {                 this.onprogress(100, 'upload completed.');                 return this.onfinishs3put(signresult);             } else {                 return this.onerror('upload error: ' + xhr.status);             }         }.bind(this);         xhr.onerror = function() {             return this.onerror('xhr error.');         }.bind(this);         xhr.upload.onprogress = function(e) {             var percentloaded;             if (e.lengthcomputable) {                 percentloaded = math.round((e.loaded / e.total) * 100);                 return this.onprogress(percentloaded, percentloaded === 100 ? 'finalizing.' : 'uploading.');             }         }.bind(this);     }     xhr.setrequestheader('content-type', file.type);     xhr.setrequestheader('x-amz-acl', 'public-read');     return xhr.send(file); };  s3upload.prototype.uploadfile = function(file) {     return this.executeonsignedurl(file, function(signresult) {         return this.uploadtos3(file, signresult);     }.bind(this)); };   module.exports = s3upload; 

any appreciated here i've been banging head against wall quite few hours now.

you can't add signed put url. works signed policy goes along post because 2 mechanisms different.

signing url lossy (for lack of better term) process. generate string sign, sign it. send signature request, discard , not send string sign. s3 reconstructs string sign should have been, request receives, , generates signature should have sent request. there's 1 correct answer, , s3 doesn't know string signed. signature matches, or doesn't, either because built string sign incorrectly, or credentials don't match, , doesn't know of these possibilities case. knows, based on request sent, string should have signed , signature should have been.

with in mind, content-length-range work signed url, client need send such header request... doesn't make lot of sense.

conversely, post uploads, there more information communicated s3. it's not going on whether signature valid, has policy document... it's possible include directives -- policies -- request. protected alteration signature, aren't encrypted or hashed -- entire policy readable s3 (so, contrast, we'll call opposite, "lossless.")

this difference why can't trying put while can post.


Popular posts from this blog