1

I looked around and just couldn't find what I'm looking for without additional plugins/libraries. I want to upload an image and process it serverside via JQuery AJAX, but I can't figure out how to pass and process it. Any help is much appreciated!

6
  • does it have to be jQuery or AJAX? I would recommend node.js for that sort of thing. Commented Oct 9, 2013 at 20:29
  • 1
    create a <form>, give it the correct attributes for posting an image to the server, set it's target at an iframe that is hidden, and then submit the form. There, you uploaded an image without reloading the page, AND, it didn't require any javascript! Commented Oct 9, 2013 at 20:29
  • 1
    AJAX does not natively support binary file transfers. You'd need to base-64 encode it, send it as a text blob in an AJAX call, decode it on the server and save it back to binary. You want to write all that yourself - go ahead. Commented Oct 9, 2013 at 20:30
  • 1
    @Diodeus well, technically you could do it with window.FormData in browsers that support window.FormData Commented Oct 9, 2013 at 20:31
  • 1
    possible duplicate of How can I upload files asynchronously with jQuery? Commented Oct 9, 2013 at 20:31

1 Answer 1

2

Though Diodeus is correct, it isn't quite that difficult. Just maddening.

HTML5 does expose what is called the FileReader API, which is still relatively new and unsupported on legacy browsers, but which will make your job easier. I have a small app which accepts images on the client side and, using the FileReader API, converts them to base-64 for uploading to the server.

The following is the function I call upon a user's uploading an image. App.FileReader is an instantiation of the HTML5 FileReader, which is declared simply like:

App.FileReader = window.FileReader ? new FileReader : null;

Upon upload, I read the image as a dataURL using the FileReader, and push the data into an unused tag. The FileReader itself retains the read data, which is why it is a good idea to only instantiate one FileReader at a time.

    if (input.files && input.files[0]) {

        if (App.FileReader) {

            App.FileReader.onload = function (e) {
                $('#createMomentImagePreview').attr('src', e.target.result);
            }

            App.FileReader.readAsDataURL(input.files[0]);

            $this.uploadedImage = true
        }

        else {
            $('#createMomentImagePreview').attr('src', 'http://d33w6ffaa49e6z.cloudfront.net/media/ImageLoaded.png');

            $this.uploadedImage = true
        }
    }

This is the AJAX call for uploading to the server, where data represents the read file, or "App.FileReader.result":

    $.ajax({
        url: '/image',
        type: 'POST',
        data: {
            image: App.FileReader.result
        }
    }).done(function(data){

        callback(data);

    }).fail(function() {
        console.log("Image upload failed!")
        alert("Sorry, there was an error uploading your image to the database.")
    })

Server-side (and I'm using Node with Express, so this might not apply), I can convert the base64 string to a Buffer (Blob) and send that up to S3 using Knox's putBuffer. This is waaaaaay simpler than actually authenticating with S3 AND trying to get it to play nice with your binary data.

if (req.body.image.match(/^data:image\/png;base64,/)) {
    var image = new Buffer(req.body.image.replace(/^data:image\/png;base64,/,""), "base64");
}

else if (req.body.image.match(/^data:image\/jpeg;base64,/)) {
    var image = new Buffer(req.body.image.replace(/^data:image\/jpeg;base64,/,""), "base64");
}

awsClient.putBuffer(image, '/' + imagePath + '.jpg', headers, function(err, stream) {

          if (err) {
            console.log(err);
            return false
          }

          res.send(200, imagePath + '.jpg')

          image = null;

        });

In either case, once you have the base64 data on your server you've made significant progress. You could use ImageMagick to handle processing as well. For what it's worth, I hope this helps you out in some way!

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks so much for the response! I'm actually already using FileReader so this just might come in handy. Right now I'm trying a hidden IFrame that will pass a javascript variable back to the parent window to denote success (or lack thereof) and don't see why it wouldn't work. If it doesn't though, I will definitely take a closer look at your solution. Thanks again!
No problem! Hmm... I should think that using a $.change() event on your file input might be a better way to listen. It will only trigger if the file upload is successful, and it's worked like a charm for kicking off my app above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.