Drag out files like Gmail

Aug 16
 
Drag out files like Gmail

Google in their quest to keep me busy in trying to figure out how they do their innovative features in Gmail are at it again. First it was drag and drop uploading which used a clever trick to make it work in Chrome which currently doesn’t support the FileReader in their stable release. Now they’ve added the ability to drag out attachments to your file system, allowing you to bypass the usual method of the save dialog.

While the first feature of drag and drop uploading I figured out quite easily, this drag out feature was a doozy.

How did I figure it out?

There were two clues which got me started. One it only works in Chrome so it had to be an extension to the current Drag and Drop API. Two, after some poking around in gmail, there was a custom attribute on the attachment link called download_url which colon separated the attachments mime type, file name and download link.

Since Gmails JavaScript is obfuscated to within in an inch of its life there was no easy way to attach the built in debugger to anything that might give it away. So I tried downloading the script and running it through various unobfuscaters which made it format nicely but I still had to work with function names like vHG etc.

My last hope was chromiums bug tracker and searching to see if any bugs or feature requests were filed that could help give it away. I knew the download_url attribute played a role and it would be set using setData method on the dataTransfer object. So I searched high and low on Chromiums bug tracker for matches to “download_url”, “downloadurl” & “downloadurl setData” nothing nada, zip. So I turned to the webkit bug tracker, still nothing! So I thought maybe Mozilla had discussed it on their bug tracker, a long shot but worth a try. Bingo! This bug led me to this bug, on webkits bug tracker don’t ask why the search didn’t bring this up, and then onto this proposal. We’re in business!

How does it work?

So we’ve found the details let’s play with it.

Update: I’ve rolled out drag to desktop across my site for all my demo source files. If you’re using Chrome 5+ just drag the “Download the source files” link to your desktop!

The above demo will, in Chrome 5+, allow you to drag any of the items to your desktop and save them without having to go through the usual save dialog process.

var file = document.getElementById("dragout");
 
file.addEventListener("dragstart",function(evt){
    evt.dataTransfer.setData("DownloadURL",fileDetails);
},false);

From the code above you attach an ondragstart event listener to something you want to “drag out” and save to your file system. On the dragstart event you set the data using the new “DownloadURL” type and pass file information to it.

In order to pass the correct information to the event we access the download_url attribute and use that for our setData call. I’ve made one change that is slightly different to how Gmail sets and gets the attribute.

<a href="Eadui.ttf" id="dragout" draggable="true" data-downloadurl="
    application/octet-stream
    :Eadui.ttf
    :http://thecssninja.com/gmail_dragout/Eadui.ttf">Font file</a>

Instead of creating a new attribute I have instead used the new custom data attributes specified in the HTML5 spec. While not officially supported by Chrome yet we can still use it and add a simple test for support and fork the code either way.

The custom attribute needs three things specified that are separated by colons in order for it to work. The files mime type, the name you wish it to be saved as (this can be anything) and the url to where the file can be downloaded from.

var fileDetails;
 
if(typeof file.dataset === "undefined") {
    // Grab it the old way
    fileDetails = file.getAttribute("data-downloadurl");
} else {
    fileDetails = file.dataset.downloadurl;
}

Above I do a check to see if the element supports the dataset attribute if not use getAttribute to grab the value.

A cool finding

Playing around with this new functionality I did find a cool side effect that if I drag a file that’s set the DownloadURL type on the setData method into a page using Firefox 3.6+ that will capture a drop event the dataTransfer file attribute will act as though it’s captured a local file and can be manipulated with the FileAPI e.g. In my font dragr web app if I drag a font file that’s been attached to an email it will render the font as though I’ve dragged it from my local file system! Doing the same with Chrome 6, which also supports file attribute on the dataTransfer property, will ignore the drop.

Predicting the next challenge from Google

So what do I think the Gmail team will do next? Since they announced, and are now starting, their 6 week release cycle of chrome. I foresee the ability to upload folders not just individual files, being able to capture a photo from your web cam straight into an embedded picture using the proposed media capture proposal. Whatever it is I’m sure it’ll knock everyone’s socks off and make me rack my brain in trying to figure it out.

Short URL: http://cssn.in/ja/028

 
 
 

Post filed under: html5, javascript.

Skip to comment form.

Comments

  1. Very well done! You are a true thinker, keep up the good work!

    Nadav, August 17th, 2010
  2. seems that it works in firefox too

    l4u, August 17th, 2010
  3. @l4u – Firefox appears to work but what it’s really doing is creating a shortcut to the anchor link where ever you drag it out to on windows. Not sure what it does on other OS platforms.

    The Css Ninja, August 18th, 2010
  4. Nice, this is pretty cool. I hate that damn save file dialog box.
    I didn’t even know you could do that in gmail.

    Jared, August 21st, 2010
  5. Great work, thanks! A quick test shows this also works for Data URLs, which thus offers an easy way to download client-generated files. Awesome!

    Alexis Deveria, August 26th, 2010
  6. @Alexis – Nice, the canvas image editors could benefit from that.

    The Css Ninja, August 27th, 2010
  7. On firefox on ubuntu it works, and it downloads the file to the desktop. (nautilus does the download job, not the browser)

    Jonathan Schemoul, August 29th, 2010
  8. Nice article! I am trying to apply this to my product, but having no success in dragging a div out of the browser window. I feel like dnd from browser to desktop is only applicable to <a> and <img>.

    What I tried to do is that when I drag a div item, I change the event object’s target/srcTarget properties to point to a hidden element that contains the data-downloadurl, but those properties (event.target/event.srcTarget) seem to be somewhat read-only.

    I cannot change the div item to <a> . Any suggestion on how I can drag this thing out without adding anything visual (such as an explicit download link or icon) to the UI?

    Thanks!

    David Tong, September 4th, 2010
  9. @David T – That’s because anchor and img elements are natrually draggable, to enable it for other elements you need to add the draggable attribute and some CSS for webkit browsers.

    <div draggable="true"></div>

    and the CSS for webkit browsers.

    [draggable=true] {
        -khtml-user-drag: element;
        -webkit-user-drag: element;
    }
    The Css Ninja, September 4th, 2010
  10. like usually, always write great article…
    its like a jutsu in ninja :P
    thanks a lot ☼ ○

    Beben, September 13th, 2010
  11. Ninja, I submitted a bug to Chromium titled “dataTransfer setData multiple formats does not work in Chrome for Windows if one of the types is ‘DownloadURL’”

    http://code.google.com/p/chromium/issues/detail?id=55071&can=5&colspec=ID%20Stars%20Pri%20Area%20Feature%20Type%20Status%20Summary%20Modified%20Owner%20Mstone%20OS

    From your research on this topic, did you find a workaround for this issue?

    Warren, September 19th, 2010
  12. @Warren – No I haven’t come across that issue thanks for the heads up.

    The Css Ninja, September 20th, 2010
  13. This is cool. I noticed that FF and IE allow drag and drop images to the desk top. I did a little test to see if that could be exploited to accomplish a wider drag out functionality.

    In FF 3.6 I was able place an image on a page using the name of a file I would ultimately like to dnd to the desktop. At render time it pointed to a gif (but was named myfile.txt). Image rendered fine. I also ensured the file was not cached by using server. I attached some synchronous AJAX code to the drag start that changed the content of myfile.txt on the server. Made it contain text.

    When the user clicks the image and DnD’s to the desktop, the file is re-loaded from the server and copied to the desktop. The result was a file named myfile.txt that contains text (not the original image).

    In IE 8.0 this did not work. I think because the file was not a known image mime type, IE would not allow me to drop it on the desktop.

    Foss Tighe, October 6th, 2010
  14. I noticed that this works fine dragging to the desktop but dragging into another HTML page (I tried with http://www.html5rocks.com/tutorials/file/dndfiles/#toc-selecting-files-dnd ) doesn’t seem to work.

    I’m in Chrome on Windows… is this the bug @Warren is talking about above?

    Anentropic, November 22nd, 2010
  15. @Anentropic – Dragging from Chrome to Firefox with the html5rocks demo loaded in Firefox will work like you are dragging a local file from your file system. This behaviour only seems to work in Firefox and not Chrome. It’s not the bug that @Warren is talking about.

    The Css Ninja, November 22nd, 2010
  16. @ninja but it doesn’t work for me, either chrome->chrome or chrome->firefox… it doesn’t work like dropping a local file. The drop page reacts, but with a blank content. This is different to if you first drag out of chrome onto the desktop and then from the desktop into the drop page.

    Anentropic, December 7th, 2010
  17. @Anentropic – It works for me from chrome 8 to FF3.6. I did a quick screencast to prove it http://screenr.com/StL this has worked for me on Vista and Win7. Haven’t tried Linux or Mac.

    The Css Ninja, December 8th, 2010
  18. @ninja hmm, I’ll try again with your fontdragr page on Win 7 some time. With FF3.6 and Chrome 8 on OSX it still doesn’t work – the drop box highlights but doesn’t receive anything (and Chrome -> Chrome it doesn’t even highlight). Probably not your code, but obviously still some issues with the browsers on this feature!

    Anentropic, December 8th, 2010
  19. It could very well be a windows only side effect. Chrome to Chrome doesn’t work it’s only Chrome to Firefox that works for me. I’m using the propriety CSS psuedo-class :-moz-drag-over for the highlight on drag over in Firefox.

    The Css Ninja, December 9th, 2010
  20. @ninja …just tried on Win 7, FF3.6.12, Chrome 8… it works! :)

    Anentropic, December 10th, 2010
  21. is there a possibility to drag out multiple files at once? Any ideas on that?

    tariq, January 29th, 2011
  22. @tariq
    Not at the moment but that would a useful addition to fleshout for the Chromium team if they ever decide to spec the downloadURL.

    The Css Ninja, January 29th, 2011
  23. Dragging out file from browser is easy, if you don’t want any script tag, you can do this.
    For example:

    <a href="http://www.google.com/logos/classicplus.png" 
        draggable="true" 
        ondragstart="event.dataTransfer.setData('DownloadURL',
        'image/png:classicplus.png:http://www.google.com/logos/classicplus.png');" 
        onclick="return false"
    >
    Drag me
    </a>

    Which do the same thing. (You can also use div instead of a)
    Read Google’s http://www.html5rocks.com/ for more info. :)

    Derek, March 23rd, 2011
  24. Great article. Great comments.

    > and the CSS for webkit browsers.

    For other browsers, it is user-select: none;

    The entire rule set:

    [draggable] {
    -moz-user-select: none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    user-select: none;
    }

    See you on Twitter: @4digitalmasters

    @4digitalmasters, April 29th, 2011
  25. Doesn’t work in Firefox 8 (FF8) on OS X Lion.

    Looks like they’ve dropped support. The only reference I could find is for extensions:

    Dragging files to an operating system folder

    https://developer.mozilla.org/User:venesa/Recommended_Drag_Types#Dragging_files_to_an_operating_system_folder

    AJ ONeal, November 12th, 2011
  26. @AJ ONeal

    This never worked for Firefox, only Chrome as they added support for the proprietry “downloadURL” type.

    Ryan Seddon, November 16th, 2011
  27. Cool! Good Job!!

    iuwei, December 25th, 2011

Trackbacks

  1. [...] » HowTo: GMail File Dragout Der CSS Ninja hat eine gute Anleitung erstellt, wie er den File Dragout von GMail entsprechend nachgebaut [...]

    HowTo: GMail File Dragout at webCONSUL, August 17th, 2010
  2. [...] Drag out files like Gmail | The CSS Ninja – All things CSS, Javascript & xhtmlthecssninja.com [...]

    Drag out files like Gmail | The CSS Ninja – All things CSS, Javascript & xhtml « Netcrema – creme de la social news via digg + delicious + stumpleupon + reddit, August 17th, 2010
  3. [...] Drag out files like Gmail | The CSS Ninja – All things CSS, Javascript & xhtml – August 25th %(postalicious-tags)( tags: javascript html5 css gmail dragdrop chrome download file reference )% [...]

    Delicious Bookmarks for August 24th through August 25th « Lâmôlabs, August 25th, 2010
  4. [...] Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]

    Ajaxian » How to Drag Out Files Like Gmail, August 26th, 2010
  5. [...] This post was Twitted by theystolemynick [...]

    Twitted by theystolemynick, August 26th, 2010
  6. [...] Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]

    How to Drag Out Files Like Gmail | pro2go Designs Blog, August 26th, 2010
  7. [...] via Drag out files like Gmail | The CSS Ninja — All things CSS, Javascript & xhtml. [...]

    Drag out files like Gmail, August 26th, 2010
  8. [...] }Brad Neuberg Read Post Ryan Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]

    How to Drag Out Files Like Gmail | DesignerLinks | Home to Web design news, jQuery Tutorials, CSS tutorials, Web Designing tutorials, JavaScript tutorials and more!, August 27th, 2010
  9. [...] 26 Aug 2010  Powered by Max Banner Ads Ryan Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]

    How to Drag Out Files Like Gmail | Programming Blog, August 27th, 2010
  10. [...] La gente de CSS Ninja ha publicado un artículo explicando como conseguirlo nosotros mismos en nuestras páginas…. [...]

    Arrastra ficheros de tu web al escritorio gracias a Javascript | aNieto2K, August 27th, 2010
  11. [...] by a blogpost of the css-ninja which i stumbled upon at ajaxian.com, i quickly hacked this jQuery plugin – [...]

    jQuery plugin download files by dragging | SalesKing Developer Blog, August 27th, 2010
  12. [...] http://www.thecssninja.com/javascript/gmail-dragout [...]

    Drag out files like Gmail, August 27th, 2010
  13. [...] Drag out files like Gmail | The CSS Ninja – All things CSS, Javascript & xhtml (tags: dragdrop file web) This entry was posted on Friday, August 27th, 2010 at 8:04 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. « links for 2010-08-24 [...]

    TempusFactor » Blog Archive » links for 2010-08-27, August 28th, 2010
  14. [...] Seddon, aka the CSS Ninja, has a nice blog post up where he reverse engineers the new feature in Gmail where you can drag attachments from an email on [...]

    How to Drag Out Files Like Gmail | freewebdesignscottsdale.com, September 9th, 2010
  15. [...] [...]

    Drag-n-drop в HTML5 - Пара слов о программировании, March 1st, 2011
  16. [...] Drag Files out of Browser onto Desktop – http://www.thecssninja.com/javascript/gmail-dragout Drag File into Browser Upload – [...]

    E2.0 Workbench Podcast 3 – HTML5, UCM and WebCenter “QuickBox” | John Brunswick, April 26th, 2011

Leave a comment