HTML5 Drag and Drop Upload and File API Tutorial

Update #3: Using the techniques outlined in this article I have rolled out and initial release of imgscalr.com.

Feel free to download the JS source (it is heavily commented) and take a look at how it was rolled out. Unfortunately the required File API support is only in Chrome and Firefox currently, Safari gets it in version 6, Opera possibly in version 11 and possibly IE 10 (9 has no support).

Introduction

Over the last day I’ve been trying to learn how to use the new HTML5 Drag and Drop API as well as the new File API. I want to create a really nice drag-and-drop experience for users trying to upload files to a webapp; much like Google just did with Drag and Drop attachments in Gmail.

They always say that the best way to learn something is to try and teach someone else, so here is my attempt at distilling this relatively new and unsupported technology down into nice diagrams, gotchas and code so you can enjoy it too.

Why do we need HTML5 for This?

Good question, and it all boils down to the information and access that an HTML5-compatible browser gives you to local resources on the person’s computer.

With an HTML5 compatible browser you get full file path information to the file that is dropped as well as the ability to open an JavaScript-based reader against the file to get it’s contents.

Without the browser supporting this directly, the browser cannot expose the full path to the file to JavaScript OR open a reader on the file. You are left relying on Flash or Java Applets to provide a DnD experience or going back to old-school POST forms where the user clicks the “Browse” button to go find a file on their hard drive and then upload it.

Known Issues

As of June 29, 2011 this code and the two APIs required for it to function work on the following browsers:

The only two browsers still not supporting both these HTML5 APIs completely are:

<“Additional details” section removed and summarized in the list above>

Understanding the HTML5 DnD and File API

Let me layout a high level abstract picture of the HTML5 Drag and Drop sequence of events so you can grok it faster, it basically looks like this (yes, I totally drew this by hand in OpenOffice Impress):

(Click to enlarge)

I created the diagram above so you could visually walk yourself through the processing of using these new features — it also helped me understand it a bit better seeing it laid out like this as well and the execution flow of the DnD and File APIs.

Let’s take a tour of the diagram, node-by-node. It goes something like this:

  1. (DnD API) Starts with the drop event when the user releases the mouse and the mouse-up event occurs.
  2. (DnD API) Get the DataTransfer object from the drop event
  3. (File API) Call DataTransfer.files to get a FileList, representing the list of files that were dropped.
  4. (File API) Iterate over all the individual File instances and use a FileReader object to read their content.
  5. (File API) Using the FileReader.readAsDataURL(file) call, every time a file is completely read, a new “data URL” (RFC 2397) formatted object is created and an event wrapping it is fired to the onload handler on the FileReader object.
    1. FYI: The “data URL” object is Base64-encoded binary data, with a spec-defined header sequence of chars. Browsers understand them.
    2. UPDATE: This was changed from onloadend to onload as Nicholas pointed out the correct usage.
  6. (File API) Now that we have the “data URL” object from the event, we can do cool things with it like replace the src attribute of an <img> tag to immediately show the value on-screen OR upload the Base64-encoded portion of the data to a server to process as binary data.

As crazy as this all looks, it works really nicely when your browser supports it.

Update #4: As of April 27, 2011 the following browsers support this: Chrome, Firefox, Safari 6+ with Opera 11.x soon-to-follow. IE likely won’t support it until version 10.

The Code

Let’s take a look at the interesting bits of code that come together to make all this happen. First you have your HTML file:

<div id="dropbox"><span id="droplabel">Drop file here...</span></div>
<img id="preview" alt="[ preview will display here ]" />

Nothing fancy here, so let’s move on.

Next we have to register handlers with all the different Drag and Drop events that can occur on our page. Let’s look at the code first:

var dropbox = document.getElementById("dropbox")
 
// init event handlers
dropbox.addEventListener("dragenter", dragEnter, false);
dropbox.addEventListener("dragexit", dragExit, false);
dropbox.addEventListener("dragover", dragOver, false);
dropbox.addEventListener("drop", drop, false);

Wow that looks really complicated! Don’t worry, the dragEnter, dragExit and dragOver handlers are all basically no-op handlers that just stop the event from propagating further. They all look like this dragEnter handler:

function dragEnter(evt) {
  evt.stopPropagation();
  evt.preventDefault();
}

You can even define a single handler like this that you can re-use for all those no-op events:

function noopHandler(evt) {
  evt.stopPropagation();
  evt.preventDefault();
}

and just register it with the “dragenter”, “dragexit” and “dragover” events.

TIP: Sam points out in the comments that if you are using jQuery selectors to try and bind the listeners, it may not work.

The only interesting handler is the drop handler, and it looks like this:

evt.stopPropagation();
evt.preventDefault();
 
var files = evt.dataTransfer.files;
var count = files.length;
 
// Only call the handler if 1 or more files was dropped.
if (count &gt; 0)
	handleFiles(files);

The first bit looks familiar; stop the propagation of the event again. Then the interesting bit starts:

  1. Get the DataTransfer object from the event.
  2. Get the list of File objects that were dropped (via a FileList) from the DataTransfer object.
  3. If we have 1 or more files that were dropped, process them with the handleFiles function.

If you scroll back up to the diagram you’ll notice these are right out of it and were already outlined above as the transition between the HTML5 Drag and Drop API right into the new File API when you ask the DataTransfer for its FileList.

Now that we have that under control, let’s take a peek at the handleFiles function:

var file = files[0];
 
document.getElementById("droplabel").innerHTML = "Processing " + file.name;
 
var reader = new FileReader();
 
// init the reader event handlers
reader.onload = handleReaderLoad;
 
// begin the read operation
reader.readAsDataURL(file);

Taking a look at this line-by-line, we have:

  1. Grab the first file from the FileList – in this tutorial we only use the first file dropped.
  2. Replace the text in the drop box with something indicating we got the drop.
  3. Create a new FileReader (new File API) to read the file contents off disk.
  4. Register an onload handler with the FileReader that will process the file after it’s read.
  5. Start the read operation; reading files in as “data URL” formatted elements. We do this because we can literally set our return value as the <img> tag’s src attribute and see them render; it’s slick!

So that was all pretty straight forward, the only magic left is to see how we handle the loaded file. It’s got to be insanely complex to make up for all the other small snippets so far right?

Nope! handleReaderLoad is deceivingly simlpe:

function handleReaderLoad(evt) {
  var img = document.getElementById("preview");
  img.src = evt.target.result;
}

And again, line by line, we are doing:

  1. Get the <img> element from our DOM.
  2. Set its src attribute value to the “data URL” formatted value read from disk; luckily browsers know how to render these things natively. Their format is really simple though and the actual image bits come in as Base64-encoded, you can see an example here.

And that’s it… awesome right?

I am not sure why I had to call evt.target.result as a few API docs I read said that the ProgressEvent‘s result would contain the object, but when I just called ‘evt.result’ I got null. I did some debugger inspection and saw that target had the result property and changed it to that.

Update #1: Scott clarified below why evt.target.result has to be called:

If you were curious, the reason you have to do evt.target.result is because the event object is essentially just a wrapper with some information about what type of event was fired, and what object raised the event. The target property returns the FileReader object “reader.” “reader” has a “result” property that gets file information when the “onload” event fires. The event class doesn’t have a result property, so “event.result” will return undefined.

Extra Snippet

For anyone wanting the exact CSS I used to make the upload box look so epic, here it is. Enjoy!

#dropbox {
	width: 425px;
	height: 300px;
	border: 2px solid #DDD;
	-moz-border-radius: 8px;
	-webkit-border-radius: 8px;
	background-color: #FEFFEC;
	text-align: center;
	color: #BBB;
	font-size: 2em;
	font-family: Arial, sans-serif;
}
 
#droplabel {
	position: relative;
	top: 40%;
}

Download Sample Code

If you would like to download the entire project created for this tutorial, you can grab it here. Enjoy!

Conclusion

When I started this little adventure I didn’t expect it to go so smoothly. At first reading through the APIs it was a bit daunting, but as I started to see more and more examples things cleared up for me.

Like I said, I’m no JavaScript guru. Some of you reading this are gurus and could have probably done this in your sleep; if you are, let me know where I could have done something better/smarter or more-gooder (that’s right, gooder).

If you have read this far I hope it helped and you can hit the ground running with the HTML5 APIs. I have no idea when Google Chrome, Apple Safari or Internet Explorer 9 will support these APIs and we can start rolling out apps using them exclusively. I think for the next few years at least having multiple modes of uploading is going to be necessary until it become ubiquitous. I was even surprised to see a site as large as Facebook use a Java Applet as an upload mechanism the other day.

Happy Coding!

References

These are links to the resources I found hugely helpful while writing this tutorial. If you get stuck either post a question below or give these a browse and see if it helps.

Update #2: Reader Woj sent in a link to his html5uploader project that works in Chrome, Safari and Firefox giving you an easy HTML5 drag and drop implementation.

Update #3: Reader Nicholas Shanks corrected the use of onloadend vs onload and the tutorial was updated accordingly.

Tags: , , , , , , , , , , , , , , , ,

About Riyad Kalla

Software development, video games, writing, reading and anything shiny. I ultimately just want to provide a resource that helps people and if I can't do that, then at least make them laugh.

, , , , , , , , , , , , , , , ,

113 Responses to “HTML5 Drag and Drop Upload and File API Tutorial”

  1. John Brown June 25, 2010 at 2:16 pm #

    Just tried this with Safari 5, and I am getting the same error as I do with Chrome.

    Thanks for the great post!

    • Riyad Kalla June 29, 2010 at 11:02 am #

      John, yea it’s a bummer. Neither Chrome 5 or Safari 5 support the new File API just yet — I think the next Chrome release well and when I went through the “HTML 5 features” for Safari 5 announcement, it didn’t say support for File API anywhere — so it’s just missing right now.

      I’m sort of surprised neither are on board with Firefox being the only one that supports it right now :(

      • Null July 5, 2010 at 6:23 pm #

        The WebKit nightly builds thankfully *do* support FileReader, though oddly the dev channel for Chrome does not. Hopefully we can look forward to this in a Safari 5.x update?

        • Riyad Kalla July 5, 2010 at 8:13 pm #

          Null, good to hear it’s in nightly, then we should all be getting it shortly in Chrome and Safari — as you said, likely a 5.1 release for both probably (Safari and Chrome).

  2. kn33ch41 July 16, 2010 at 5:45 pm #

    Nice work, but regarding the presentation I have a suggestion: display all the code with their function names, curly braces and all. You can optionally provide all the source in a single HTML file for download, so a developer can just drop the file on their server and use the example immediately.

    You’re the first article I’ve read on the process, and will not be the last. Thank you for the insightful walkthrough!

    • Riyad Kalla July 16, 2010 at 6:34 pm #

      kn33ch41,

      Good pt. If I update the tutorial or do another one I’ll include full source files for a better “download and play” experience.

  3. amt August 16, 2010 at 1:37 am #

    Thank you, that is a good effort, but i want to ask about something.

    First, i tried the demo on Chrome 6, Firefox 3.6, and IE, but i couldn’t drag files, only upload multi files, so what’s wrong ?

    Also, can File API help to return the full file path of the file, i need that, but i read that the name attribute is only have the file name not the path.

    So, is there any other way to get full file path ?

    Thank you in advance…

    • Riyad Kalla August 16, 2010 at 2:45 am #

      amt,

      I’m not sure if Chrome 6 *does* support the File API correctly yet, I haven’t tried it. Firefox 3.6 is the only one that I tried that does seem to fully/correctly support it when I wrote this tutorial, so you might want to start there with the testing.

      IE is a mess and likely won’t ever support this correctly. Even the IE 9 preview I tried didn’t seem to support any of the DND or File APIs.

      When you said you couldn’t “Drag files” did you mean when you dropped them, only the first one loaded? The reason for that is because of a code simplification I made above.

      Look at the code snippet that starts

      ======================
      var file = files[0];

      document.getElementById(“droplabel”).innerHTML = “Processing ” + file.name;
      ======================

      I am just grabbing the first file of the group of files that are dropped — you will want to process each one that is dropped and change this to a loop instead.

      Also the File API *should* be giving you the full path if it is implemented correctly per the File API spec. If you are using a browser that doesn’t support it correctly, you get weird things like just the “name” property containing just the local name of the file, not the full path.

      This is one of the down sides of this API, if your browser doesn’t implement the File API, your code is *hopeless*. There is literally no way to get access to the path information you need to execute the upload.

      I spent a few hours (after writing this guide) researching techniques to work around browser limitations of the File API impl, and there are no JS+HTML only solutions, the reason is because the browser just doesn’t expose that information without implementing the File API.

      You have to resort to something like Java or Flash DnD.

      Hope that helped!

      • amt August 17, 2010 at 2:47 am #

        Thank you about reply,

        I search now about File API and its ability to return full file path, Also the Google supporting to File API.
        But i still can’t run your example well, may i collect code in wrong way, so can you put it here as a one whole file or even can i get it from you by e-mail ?

        Also, there is a something, i follow bug solution on Mozilla to return file path and it works, but still show “UNSAFE” message to user and ask him to Allow or Deny, i want to prevent this message from appearing, do you know any thing about that ?

        sorry for disturbance, and your help is appreciated..

        Thank you sir,

        • Riyad Kalla August 17, 2010 at 11:11 am #

          amt,

          I just included a link to the source code for the project created with this tutorial, you can grab it here.

          As for the “UNSAFE” issue in Mozilla, I never saw anything like that. Can you post a screenshot of what you are seeing?

          • amt August 21, 2010 at 11:28 pm #

            Mr.Riyad,

            Thank you very much, I tested your example and it worked on Firefox 3.6.8 and Google Chrome 6 but not on IE and Safari, as you said sir.
            I’ll continue now in File API and file path.

            About Firefox msg,

            This msg appears when we access file path from user machine, this code is HTML and Javascript, not HTML5.
            It was Fixed Issue at Mozilla at this link:

            https://bugzilla.mozilla.org/show_bug.cgi?id=143220

            Comment # 49 and # 50

            ONLY, to use full file path and catch it I did only alert to fileName variable like this: (Source code from last link DON’T have this alert)

            ————————————————————–
            var fileName=fileBrowser.value;

            var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
            try
            {
            // Back slashes for windows
            alert(“filePath : “+fileName)
            file.initWithPath( fileName.replace(/\//g, “\\\\”) );
            }
            ——————————————————————————–

            Thank you Sir,

            • Riyad Kalla August 22, 2010 at 6:11 am #

              amt, I’m glad it helped. You are most welcome.

              Also appreciate the link to the Mozilla bug with regard to that error warning, that will help other folks running into that same issue.

  4. Riyad Kalla August 17, 2010 at 11:11 am #

    Guys sorry for the delay. I packed up the example project and added a section to the tutorial above with a link to it.

    You can grab it here.

  5. Scott October 8, 2010 at 6:24 pm #

    If you were curious, the reason you have to do evt.target.result is because the event object is essentially just a wrapper with some information about what type of event was fired, and what object raised the event. The target property returns the FileReader object “reader.” “reader” has a “result” property that gets file information when the “onload” event fires. The event class doesn’t have a result property, so “event.result” will return undefined.

    • Riyad Kalla October 14, 2010 at 3:06 pm #

      Scott, I was very curious about that. Thank you for the clarification. I’ll update the post with the information incase others have the same questions.

    • Mori May 17, 2014 at 9:17 pm #

      There’s something I don’t understand: why isn’t “reader” or “this” used instead of “event.target” while they all refer to the FileReader object:
      http://jsfiddle.net/Mori/tJBHZ/

  6. Tim October 31, 2010 at 6:35 pm #

    Hey,

    Thanks for this tutorial of sorts. I was interested in this subject but a image hosting website.
    http://min.us/

    This however does support the Chrome browser and I am still determined to find out how they do it.

    This is great work for your first day in jQuery and I have to admit I would never be able to do that myself.

    I am going to add an exception to the code that if the browser is not supported it has a standard upload form.

    I will post back here with my results.

    Thanks,
    Tim

    • Riyad Kalla November 2, 2010 at 9:41 am #

      Tim, min.us is *seriously* slick, thanks for the heads up on that. Let us know what you come up with in your own development.

    • John @ Minus November 9, 2010 at 5:05 pm #

      Hi

      This is John from Minus (http://min.us) . Thanks for sharing Minus and if anyone has feedback or suggestions please feel free to contact us.

      John@min.us

  7. Woj November 8, 2010 at 2:08 pm #

    Hi,

    Maybe You will be interested with our small library for drag & drop upload files support. Library is availabe at http://code.google.com/p/html5uploader/ and it works on Firefox, Chrome and Safari. It doesnt require any JS frameworks.

    • Riyad Kalla November 9, 2010 at 7:08 pm #

      Woj, that is *seriously* handy. I’m updating the original post with a link to your project, thanks for sharing that.

      • Woj November 10, 2010 at 2:02 am #

        Glad to hear it, thanks for good word and link :-)

  8. Joseph January 25, 2011 at 6:33 pm #

    Your drag&drop doesn’t work for me (chrome 8)… In firefox it does

    • Riyad Kalla January 28, 2011 at 8:45 am #

      Joseph, which version of Chrome? I’m testing this impl in Chrome 8 (latest stable) and it’s working fine.

      Pop open the JavaScript Console then try the DnD and see if you are getting an error that might help pinpoint what’s wrong.

      • MooCow September 11, 2011 at 11:33 am #

        Doesn’t work on Chrome 13.0.782.220 running on Mac OS X 10.6.8.

        Instead of accepting my image, Chrome is simply showing me the JPEG image I’m dropping on it, like there’s no upload form or drag’n drop area at all.

  9. cfcees February 12, 2011 at 5:05 am #

    Excellent article. I have used a similar approach. Works fine in Chrome 10, still not in Safari 5, though. I have found a workaround for not getting access to the full path. I simply store the dataURL in sqlite. This way I can retrieve it later on. Good part is it does not only work for images but als for PDFs. Just include an “embed” tag like this:

    “”

    • Riyad Kalla February 14, 2011 at 8:34 pm #

      cfcees – looks like the File API support is coming in Safari 6 and currently works in the nightlies from what I’ve read.

  10. Rüdiger Kurz March 9, 2011 at 3:38 am #

    Hi,

    this is Rüdiger I’m a developer from Alkacon Software GmbH in Cologne, Germany. This year we are planning to release our new version 8 of OpenCms. Therefore we want to support our customers with a FileApi / FormData based upload functionality. This new upload feature should also provide drag and drop.

    Szenario: drag a folder on to the defined dropzone
    Target: detect that a folder was droped

    Unfortunately I don’t see a solution. Do you have any ideas?

    Thank you for the help
    r.kurz@alkacon.com

    • Riyad Kalla March 10, 2011 at 8:28 am #

      Rüdiger,

      If you need to support users dragging and dropping folders, you won’t be able to do that consistently/cleanly with the HTML5 File API (reference) – you would need to look at a Flash or Java Applet uploader.

      If you just want to allow DnD file upload, you can use this guide and it will work in Chrome stable, Firefox stable, Safari 6 and hopefully Opera 11 soon — no IE9 support though.

      Keep in mind that the number of drag and dropped files can get capped at what your browser is willing to send; in Chrome this defaults to something like 7, so if someone drag and drops 100 files into the window, I saw some use-cases where only 7 are ever given to the File API to read. It was an annoying side effect, I didn’t test it much beyond that.

      But some companies, like SmugMug, have extensive/functional HTML5 uploaders that get past that issue just fine it seems, I haven’t looked at the JS Yet to see how, but it seems there is a way.

      • Rüdiger Kurz March 10, 2011 at 10:12 am #

        Thank you for your response…

        I did not explain my target exactly, sorry:

        - What I want is to inform the user that he is not able to drop folders

        - What I don’t want is to handle all the files inside a folder

        The File API lacks in the capability to differentiate between files and folders. I have never seen a API which is dealing with files that can’t differentiate between files and folders. So every API that is dealing with files should implement a method like:

        boolean isFile() or boolean isFolder()

        I’m very disappointed about that.

  11. Shadow March 21, 2011 at 12:54 pm #

    Nice work. Thank you for your help to the community, with this great example.
    Any idea on how could i download to my Hard-drive a file i just uploaded, after editing it, using Chrome ?

  12. reelfernandes April 25, 2011 at 4:21 pm #

    Doesn’t work with Chrome 11. Just navigates to the file path to display the image in the browser window, like ever before. = ( Still using Flash Player for local file access I guess.

    • Riyad Kalla April 26, 2011 at 4:54 pm #

      reelfernandes, if you go to imgscalr.com and DnD an image, does that work in Chrome 11?

      Sounds like they might have broken something… Chrome 7,8,9,10 + Firefox 3.6/4.0 all work. Waiting on Safari 6 for “standard” support, Richard pointed out that Safari 5 *can* work with some minor modifications to the code.

      I need to update the article with a link.

  13. Richard York May 4, 2011 at 7:09 pm #

    When you say that Safari 5′s implementation is “non-standard” or requires “Safari-specific” code, this is not true. If that were the case, then why have both Google and Mozilla implemented the FormData object introduced in Safari 5? The demo on my site runs in Safari 5, Chrome and Firefox, unmodified. Perhaps Safari 6′s implementation is more complete, but Safari 5′s implementation definitely shouldn’t be called non-standard.

    • Riyad Kalla May 6, 2011 at 9:58 am #

      Richard, I had drawn my own (incorrect) conclusions. Thanks for the correction, I updated the post.

  14. barry May 11, 2011 at 2:42 pm #

    Hi,

    this no longer appears to work in firefox 4.0.1, it just loads the file in the browser instead. I’ve tried Richards version and the appears to work fine.

    Cheers.

    • Riyad Kalla May 12, 2011 at 7:09 am #

      barry, does uploading to http://imgscalr.com/ work for you? That uses this code as the basis for the impl. Just tested in FF 4.0.1 (Win7) and it worked… are you on Windows as well? I might have a use-case I need to re-address.

      • Mickael May 12, 2011 at 9:11 am #

        No it doesn’t upload ( Firefox 4.0.1 on ubuntu Linux )

        • Riyad Kalla May 13, 2011 at 6:27 pm #

          Mickael,

          I can’t reproduce this; I just booted FF 4 on FC 15 beta 64-bit and it uploaded fine.

          In the off chance that you already have Firebug installed, would you mind bringing up the console when you visit the site and see what errors are getting logged? If you don’t have FB installed, no worries, I’ll keep testing and see if I can reproduce it.

          • barry May 17, 2011 at 2:40 pm #

            Hi Riyad,

            sorry for the delay in getting back to you. The drag and drop on imgScalr works fine, just not on this page?

            I’m on a Mac.

            Cheers,

            James

            • barry May 17, 2011 at 2:41 pm #

              Sorry, i forgot to mention that i’ve tried tracking the issue in firebug, but it’s not possible, as i get booted off the page when the jpg is loaded.

              • Daralee February 29, 2012 at 10:22 pm #

                Hi Michael I was using Google’s Chrome boewsrr. However, out of curiosity, because I thought it may have something to do with Chrome specifically, I was able to see it in Firefox and Safari but interestingly enough, NOT in Internet Explorer. Thanks for bringing that to my attention! I’ll have to make note of it in the blog post itself.

  15. Matias May 20, 2011 at 2:50 am #

    Hi, thanks for you post.
    I just wanted to note that dragexit is deprecated. You should use dragleave instead.

    • Krystian July 5, 2011 at 5:36 am #

      In Google Chrome 12.0.742.112 dragexit dosen’t work.

  16. nooruddin June 1, 2011 at 3:08 am #

    I want to make a functionality into my flex project wherein the user just drag and drop the files into a list or anything and the file gets uploaded to the server.
    I am making a web application using flex not an Adobe AIR desktop app.

    • Riyad Kalla June 1, 2011 at 8:28 am #

      nooruddin, I am not familiar with Flex… if it’s a front-end technology like Flash, then you can probably find a drag and drop upload widget pre-made that you can use. If Flex is more of a back-end technology (like Servlets in Java) then you can use the JavaScript from this tutorial to upload files to a back end service or something like that.

  17. Sam Saccone June 30, 2011 at 5:12 pm #

    your event listeners for dragexit dragover and dragenter are not supposed to be capitalized

    • Riyad Kalla July 1, 2011 at 1:00 pm #

      Sam, why would the case of the function name reference matter? I understand why the name of the event handler itself matters (they are all lowercase) but when I pass in the function reference, why would the case matter there?

      • Sam Saccone July 1, 2011 at 8:42 pm #

        opps looks like i misread it on the first time around, sorry about that :)

        • Riyad Kalla July 2, 2011 at 3:08 pm #

          No worries, I just wanted to make sure I wasn’t doing something wrong. Thanks for following up.

          • Sam Saccone July 2, 2011 at 3:18 pm #

            yeah no problem, you might want to mention that using a jquery selector $(‘#dropArea’)[0].bind(‘drop’,dropAction); does not work for some reason, I know that tripped me up for a while, Thanks tho for the great resource

            • Riyad Kalla July 4, 2011 at 10:36 am #

              Ahhh, good find. Added a TIP to the article in case anyone else runs into that. Thanks.

            • Exception July 20, 2011 at 8:58 pm #

              You can not use bind with those events because jquery does not normalize native events. To use jquery selectors you should use it like:

              $(‘#dropbox’).get(0).addEventListener(‘drop’, dropAction, false);

              • amiuhle September 29, 2011 at 7:38 am #

                That’s wrong. You just shouldn’t use $(‘…’)[0] because that will return the HTML Element, and not a jQuery Object.

                $(‘#dropbox’).bind(‘drop’, function() {}) will work just fine!

                • Jon November 24, 2011 at 4:19 pm #

                  Not necessarily. @Exception is correct.
                  http://weblog.bocoup.com/using-datatransfer-with-jquery-events

                  But if you do this first, it will work.
                  jQuery.event.props.push(‘dataTransfer’);

                  Perhaps the dataTransfer event property is available in later jquery versions.

                  Good post…

              • gash February 1, 2012 at 11:54 pm #

                Jquery works fine if you use the original event, which jquery keeps a reference to. You can do so as follows:

                $(‘#someEl’).bind(‘drop’, function(e){
                e = e.originalEvent;
                e.stopPropagation();
                e.preventDefault();
                // Do your thing
                });

                • Riyad Kalla February 2, 2012 at 1:28 pm #

                  Great tip Gash, appreciate you adding that to the discussion for the jQuery-ers among us.

  18. John McMillion August 7, 2011 at 12:38 pm #

    I couldn’t get things to work in IE 10 PP2. When I drag the image over, the cursor changes to a red circle with a slash through it. And dropping just opens one of the images in the browser.

    However, it’s worth mentioning it is possible to get drag and drop file upload and progress bar to work in Safari 5.1, but not the thumbnail preview.

  19. Mike September 13, 2011 at 7:47 am #

    Quick question, say I want to upload the file to a server… how would I go about doing this? I’ve tried some crazy JQuery and JavaScript, tried PHP and I just can’t seem to figure this out. Any help would be much appreciated. Thank you.

    • Riyad Kalla September 13, 2011 at 8:49 pm #

      Mike, if you head over to imgscalr.com, view-source, then grab main.js, you’ll find all the code you need to do the upload. Essentially posting the contents of the file objects to a server-side script to accept and decode the information (typically Base64) back into a binary file.

      • Mike September 16, 2011 at 7:28 am #

        Thank you very much. This will be a big help!

  20. Nathan October 12, 2011 at 4:12 am #

    Riyad, thanks for this post, I’ve downloaded the source but in Google Chrome version 14, I keep getting a security error when dropping an image. It says ‘it is determined that the file has changed on disk since the user selected it’. Do you know how to solve this please?

    Thanks,
    Nathan

    • Nathan October 12, 2011 at 6:10 am #

      I’ve solved it, it was because I was accessing my index.html file through file:// in the browser instead of from a webserver.

      • Riyad Kalla October 12, 2011 at 7:38 am #

        Woops, I should have kept reading first before replying, glad it works!

    • Riyad Kalla October 12, 2011 at 7:38 am #

      Nathan… hmmmm, I’ve never actually seen that dialog before.

      If you go to imgscalr.com and drag and drop an image, does that work just fine without a warning?

  21. Chris October 12, 2011 at 5:08 pm #

    I can’t seem to get the loop to work with this for multiple image drags. Can anyone provide an example for someone that tries to drag > 1 image to the webpage.

    • Riyad Kalla October 13, 2011 at 11:35 am #

      Chris, if you go to http://imgscalr.com and view-source, then grab the main.js file — that implements multiple file upload and is clearly documented.

      • Chris October 13, 2011 at 11:46 am #

        Awesome, I see it. Thanks!

  22. ItsLeeOwen November 5, 2011 at 10:05 pm #

    Doesn’t work in Chrome 15.

    • Riyad Kalla November 9, 2011 at 1:56 pm #

      Lee, what is running at imgscalr.com works in all the browsers I’ve tested in (even IE 10)… still waiting on Opera to add DnD API though.

  23. Henrietta November 16, 2011 at 6:41 pm #

    I don’t know if the event name changed or what during some update, but the “dragexit” event did not pickup for me. I used “dragleave” instead and that worked. I’m on Chrome 15/FireFox 8

    • Riyad Kalla November 17, 2011 at 12:48 pm #

      Henrietta, thank you for the heads up. It’s possible the DND API support has changed or become more normalized across browsers. Even though this is roughly the same code running on imgscalr.com it seems that it behaves differently.

      I am waiting for Opera 12 to add DND support and then I’ll rewrite the entire tutorial using code that works on *all* browsers out of the box and easy to download/test.

      I’ll include some Java Servlets to mock the dnd-to-server scenario and a few other things that will be handy.

  24. Nicholas Shanks December 5, 2011 at 8:12 am #

    You need to amend your example code.
    The onloadend event is supposed to be for cleanup (removing progress bars, etc) and is called after one of onload (for success), onerror (for failures), or onabort (for user cancellations)
    You cannot therefore assume that you will have valid files in the onloadend handler, and should instead be using onload.

    You will need to amend your overview diagram and PDF to match.

    • Riyad Kalla December 5, 2011 at 9:41 am #

      Nicholas, thank you for the correction; I’ve updated the tutorial.

      • Nicholas Shanks February 3, 2012 at 3:56 am #

        The URL in list item 5 of the Understanding section still links to the wrong spec section, and the anchor is broken by the italic tag, wrap the anchor around the whole phrase instead of using two links pointing to the same place.

        • Riyad Kalla February 3, 2012 at 3:32 pm #

          Thank you Nick, should be fixed now.

  25. Nicholas Shanks December 5, 2011 at 8:12 am #

    Hmm, where’d the URL go?

    https://developer.mozilla.org/en/DOM/FileReader#section_16

  26. Grant Kimball December 27, 2011 at 10:37 pm #

    Great Tutorial!

    Quick question, where is the script the determines when the upload is complete? i.e. once upload complete, display message. and continue. etc.

    Thanks again,

    Grant

    • Riyad Kalla January 4, 2012 at 10:11 am #

      Grant, sorry for the delay in responding. I think it would be easier to just view-source on imgscalr.com and open the main.js file — down at the bottom are all the event handlers that display status updates when something happens to the upload (error or complete).

      • Grant Kimball January 4, 2012 at 10:23 am #

        Thanks Riyad,

        Got it. Now I just need to figure out how to upload in the form of “DATA:” Is it similar to $_FILES ?

        Anyways,

        Thanks again!

        G

  27. uday February 23, 2012 at 3:27 am #

    Hi, I am going make application like twitter but my own application do not want to use api of twitter so can you please tell me if i Use HTML 5 to develop application does it good idea? and if you know any sample Twit application but not twitter can you please suggest me. Thanking you in advance

    • Riyad Kalla February 23, 2012 at 9:16 pm #

      uday, unfortunately that is too open-ended of a question. I can’t provide any guidance.

  28. Eion Robb July 10, 2012 at 10:08 pm #

    Works in Opera 12 :)

    • Matthew Moran August 8, 2012 at 9:46 am #

      I’m new to HTML 5 and to asp.net – but I have an ASP.net app that tracks some project information and would love to add a drag and drop file function.

      How do I process – post drag – to an asp.net (c#) page?

      At the time they drag and drop I will have some key pieces of data defined – the project they are in and the current user. I will then time stamp the upload and allow them to enter some notes about the file uploaded.. I don’t really need a preview per se as most files will be pdfs or documents.

      Any insight would be appreciated.

  29. Khoi Vu Dinh August 23, 2012 at 7:16 pm #

    I’ve succeeded in using jQuery bind. I found out that we need cancel 2 events at least, ‘dragover’ and ‘drop’.

    here is my code:

    $(‘#droparea’).bind(‘dragenter dragleave’, function() {
    $(this).toggleClass(‘drag’);
    }).bind(‘dragover’, noopHandler).bind(‘drop’, function(e) {
    // cancel event
    noopHandler(e);

    $(this).removeClass(‘drag’);

    handleFileSelect(e);
    });

    hope you will be happy with this :)

  30. Chirag Mehta August 29, 2012 at 6:05 am #

    Great post!

    Need small help – How can I make drag of emails or email attachments from email client to directly upload via this Drag n Drop (ie drag emails from outlook and the html5 drag drop uploads them).

    Currently I’m able to do that only after exporting emails or emails attachments to local drive, and then dragging them over drag zone to upload, I’m not able to do it directly. Am I missing something?

    Thanks a lot in advance!

  31. Fernando February 1, 2013 at 11:34 am #

    Thank you that really helped A LOT.

  32. Stuart P February 14, 2013 at 3:47 am #

    Thanks for the tutorial. By the way I spotted an error (hopefully this wont get reformatted)

    if (count > 0)
    handleFiles(files);

    Should be
    if (count > 0)
    handleFiles(files);

    • Stuart P February 14, 2013 at 3:49 am #

      Doh! The greater than symbol keeps getting converted to/from its code making this confusing. When I entered the code in the comment it got converted to the correct symbol.

  33. Mike D May 31, 2014 at 9:02 am #

    Riyad,

    Excellent tutorial! Are you aware of a solution for handling files with commas in their name?

    Thanks,
    Mike

Trackbacks/Pingbacks

  1. HTML5 Drag and Drop and File API Tutorial | The Buzz Media | techlife - June 10, 2010

    [...] HTML5 Drag and Drop and File API Tutorial | The Buzz Media Related [...]

  2. How to drag and drop files using HTML5 example | Netvivs - May 14, 2011

    [...] you understand the process behind this previous site , and you can learn and read more about it here. Related posts:Infolinks APICreating online campaigns and best practicesTriple redundant tracking [...]

  3. AS3 and HTML5 drag and drop | MoodShare - June 19, 2011

    [...] http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ [...]

  4. HiddenTao › Javascript client-side file generation and download - July 4, 2011

    [...] – up-to-date drag & drop tutorial. * http://code.google.com/p/html5uploader/ – cross-browser file drag and drop upload library, though still won’t work without a [...]

  5. Drag and Drop File Upload and Processing via File API | Fuzzy Tolerance - July 25, 2011

    [...] helpful links: http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ [...]

  6. Drag Drop and Save as image in PHP using Jquery | SeekPHP.com - September 17, 2011

    [...] you mean like this or this? It can be done with HTML5 and JavaScript, or with Flash or Java, as in the first two [...]

  7. 为开发者和设计者准备的 HTML5 文件上传教程 » 全信息 - January 17, 2012

    [...] HTML5 拖放式文件上传的 API 教程 [...]

  8. For developers and designers to prepare the HTML5 file upload tutorial - Open News - January 18, 2012

    [...] HTML5 drag and drop file upload API Tutorial [...]

  9. Sandip Chavda » Blog Archive » HTML5 File Uploading Tutorials for Designers and Developers - January 20, 2012

    [...] HTML5 Drag and Drop Upload and File API Tutorial [...]

  10. Drag and Drop asynchronous file upload with HTML 5, File API, XMLHttpRequest and Asp.Net MVC 3 « thewayofcode - February 25, 2012

    [...] links http://html5demos.com/file-api http://www.w3.org/TR/html5/editing.html#dnd http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ http://www.w3.org/TR/FileAPI/#dfn-file FileReader API http://www.w3.org/TR/html5/dnd.html DnD API [...]

  11. 8 Best HTML5 Drag Drop Tutorials - Design Freebies - April 11, 2012

    [...] 3. HTML5 Drag and Drop Upload and File API Tutorial [...]

  12. How do I check for a bracket in the file name of the a drag and drop file in javascript? | PHP Developer Resource - May 23, 2012

    [...] found a pretty good link for you: HTML5 Drag and drop file api tutorial Tagged: drag-and-dropHTML5JavaScriptquestions /* * * CONFIGURATION [...]

  13. HTML5 Drag-n-Drop загрузка файлов | - May 29, 2012

    [...] HTML5 Drag and Drop Upload and File API Tutorial [...]

  14. file upload using drag drop | Easy jQuery | Free Popular Tips Tricks Plugins API Javascript and Themes - June 3, 2012

    [...] see http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ Tagged: asp.net, drag-and-drop, file-upload, javascript, jquery, questions /* * * [...]

  15. 10 Useful HTML5 Drag and Drop Tutorials - December 20, 2012

    [...] HTML5 Drag and Drop Upload and File API TutorialOverview of the Drag and Drop API and how to use it to create a drag and drop uploader. [...]

  16. Simple HTML5 Drag, Drop and upload JQuery plugin « Mental Jetsam - January 21, 2013

    [...] with HTML5′s ability to handle drag and drop and auto upload items to a server, found at HTML5 Drag and Drop Upload and File API Tutorial. The code below implements this as a very simple JQuery plugin and current this only works on [...]

  17. 通过 HTML5 来文件上传教程 | E威客 - October 11, 2013

    [...] HTML5 拖放式文件上传的 API 教程 [...]

  18. HTML5的File API应用丨前端193 - February 8, 2014

    [...] HTML5 Drag and Drop Upload and File API Tutorial [...]

  19. Drag-and-Drop Upload | webstefftec - June 4, 2014

    [...] http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ [...]

  20. [RESOLVED]How to call drop event for form using js | ASP Questions & Answers - July 3, 2014

    [...] http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ [...]

  21. [RESOLVED]Drag and drop using file upload control and in form in asp.net | ASP Questions & Answers - July 3, 2014

    [...] http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ [...]

  22. [RESOLVED]How to call drop event for form using js | ASP Web Form Data Control - July 6, 2014

    [...] http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ [...]

  23. [RESOLVED]Drag and drop using file upload control and in form in asp.net | ASP Web Form Data Control - July 6, 2014

    [...] http://www.thebuzzmedia.com/html5-drag-and-drop-and-file-api-tutorial/ [...]

Leave a Reply


eight − 2 =