3

Alright, in this phonegap app I start with a huge image file from the device's camera.
Then I reduce the resolution and allow the user to crop it using javascript canvas and some very cool code called darkroomJS. At the end darkroomJS uses toDataURL() method to get base64 data out of the canvas.

Now I need to upload it to Amazon S3.

I can upload a file from my computer to S3 using a form just fine. What I'm working on is sending the base64 data.

I also have a function that converts the base64 data into a blob. (which I've read will be required, but I'm open to other ideas).

 <form action="https://mybucketname.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
      <input type="" id="key" name="key" value="uploads/${filename}">
      <input type="" id="AWSAccessKeyId" name="AWSAccessKeyId" value="YOUR_AWS_ACCESS_KEY"> 
      <input type="" id="acl" name="acl" value="private"> 
      <!-- <input type="" id="success_action_redirect" name="success_action_redirect" value="http://localhost/"> -->
      <input type="" id="policy" name="policy" value="YOUR_POLICY_DOCUMENT_BASE64_ENCODED">
      <input type="" id="signature" name="signature" value="YOUR_CALCULATED_SIGNATURE">
      <input type="" id="Content-Type" name="Content-Type" value="image/jpeg">
<!--       <input id="file" name="file" >  -->
      <br> 
      <input type="submit" value="Upload File to S3"> 
    </form> 

I write in the credentials using jquery after they are obtained from my server. That part works fine.

The trouble is how do I put a blob in the form?

I've tried two methods. Setting the value with jQuery.

$page.find("#file").attr('value', blobData); //inserts the string [object Blob] text into the field and ships it to S3, not very useful

also I've tried:

        var fd = new FormData(document.forms[0]);
        fd.append('file', blobData);

//has no effect; S3 then complains that it was expecting a file, and didn't get one.

What am I doing wrong? How can I make this work?

zstew
  • 1,195
  • 8
  • 11

1 Answers1

3

Alright, got something that works:

I guess having the form actually rendered on the page kinda forces the browser to stringify the blob.
The function s3Man.getS3Policy just makes a AJAX request to my sever to get a signed s3 policy, keys, etc.

this.uploadBase64ImgToS3 = function(base64Data, filename, callback){
    var xmlhttp = new XMLHttpRequest();    
    var blobData = dataURItoBlob(base64Data);
    var contentType = false;
    if (filename.match(/.png/)) var contentType = 'image/png';
    if (filename.match(/.jpg/)) contentType = 'image/jpeg';
    if (!contentType){
        xStat.rec("content type not determined, use suffix .png or .jpg");
        return;
    }

    s3Man.getS3Policy(filename, function(s3Pkg){
        console.log("policy:", s3Pkg);
        var fd = new FormData();    
        fd.append('key', s3Pkg.filename);    
        fd.append('acl', 'public-read');    
        fd.append('Content-Type', contentType);    
        fd.append('AWSAccessKeyId', s3Pkg.awsKey);    
        fd.append('policy',  s3Pkg.policy);
        fd.append('signature', s3Pkg.signature);    
        fd.append("file", blobData);
        xmlhttp.open('POST', 'https://swoopuploadspublic.s3.amazonaws.com/', true);    
        xmlhttp.send(fd);
    });
}
Ahmed Hashem
  • 4,675
  • 3
  • 21
  • 28
zstew
  • 1,195
  • 8
  • 11