File upload to server with .drop() ?

Hi. I've been loving .drop() to upload files to the browser (so quick!). But coming up blank looking for an example of taking it the next step: uploading from browser to server.

There are a ton of file upload examples using ajax/etc all over the web. But I'm missing the piece that takes the data created by .drop(). What am I not understanding about the data that drop() delivers? Have even tried copying and pasting the data from f.data from the console and into a new file and saving, but that doesn't work either... Seems like I'm missing something fundamental?

Here's some sample code:

var xhr = new XMLHttpRequest();
var formData = new FormData();

function gotFile(f) {
   console.log('gotFile: ' + f.name + ' ' + f.size + ' ' + f.type);
  formData.append('photos[]', f.data, f.name); //FAILING HERE, TypeError: Argument 2 of FormData.append is not an object.
  // Open the connection.
  xhr.open('POST', 'upload.php', true); //an upload script on server
  // Send the Data.
  xhr.send(formData);
}
// Set up a handler for when the request finishes.
xhr.onload = function () {
  if (xhr.status === 200) {
    // File(s) uploaded.
    console.log('uploaded');
  } else {
    console.log('upload error');
  }
};

Answers

  • Maybe this is just an issue with how FormData works I suppose.

    However, even if the case, still not sure where the actual correct image file data is - if not in f.data. When I save f.data to a standalone file with correct image extension, I get an error: "The image "image.jpg" cannot be displayed because it contains errors.

  • Doesn't look like too great a mystery to figure out what drop() delivers - e.g. I just amended the example code as follows:

    function setup() {
      var c = createCanvas(100, 100);
      background(200);
      textAlign(CENTER);
      text('drop image', width/2, height/2);
      c.drop(gotFile);
    }
    
    function gotFile(file) {
      // show the contents in the console
      console.log(file);
      var img = createImg(file.data).hide();
      // Draw the image onto the canvas
      image(img, 0, 0, width, height);
    }
    

    When I drop a jpeg the file.data looks very much like a base64 encoded image to me. There's plenty of info available on submitting that to a server with JavaScript ;)

  • edited January 2017

    Is it possible to get the original file instead of the base64 representation?

    To upload the image, it'd be easier to upload the file (rather than to have to deal with the base64 encoded string). Is that original file anywhere? I've been fiddling with this for a few weeks - can't seem to get to the bottom of it.

    Ideally, I'd get the same data object that's generated by a standard browser file upload button. As in the HTML element: input type="file"

    Also, in my research of base64 format, it seems that it's intended for smaller inline images. Is it appropriate for P5 to encode every image into base64? If I've got dozens of large size images on the canvas, I'm going to blow out my browser memory, yes?

  • edited January 2017

    Oh man, think I finally got it. Need to convert base64 image into a blob as follows:

    
    function gotFile(f) {
      var base64result = f.data.substr(f.data.indexOf(',') + 1); //take out the leading base64 description, which seems to mess things up
      var blob = b64toBlob(base64result, 'image/jpeg'); //enhance this to support common image formats
     //then upload this blob as you would a typical input type=file
    } 
    
    //from: http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
    function b64toBlob(b64Data, contentType, sliceSize) {
      contentType = contentType || '';
      sliceSize = sliceSize || 512;
    
      var byteCharacters = atob(b64Data);
      var byteArrays = [];
    
      for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        var slice = byteCharacters.slice(offset, offset + sliceSize);
    
        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
          byteNumbers[i] = slice.charCodeAt(i);
        }
    
        var byteArray = new Uint8Array(byteNumbers);
    
        byteArrays.push(byteArray);
      }
    
      var blob = new Blob(byteArrays, {type: contentType});
      return blob;
    }
    
    
Sign In or Register to comment.