Drag and Drop File Upload in Classic ASP

One property turns any element into a drop zone — plus how it works underneath.

How drag and drop actually works

Dropping a file on a web page is three DOM events and one object. The browser hands you real File objects in event.dataTransfer.files — the same objects a file input produces — so everything downstream is identical to a normal upload.

var zone = document.getElementById("dropzone");

// you MUST cancel dragover, or the browser navigates to the file instead
zone.addEventListener("dragover", function (e) {
    e.preventDefault();
    zone.classList.add("is-over");
});

zone.addEventListener("dragleave", function () {
    zone.classList.remove("is-over");
});

zone.addEventListener("drop", function (e) {
    e.preventDefault();
    zone.classList.remove("is-over");

    var files = e.dataTransfer.files;      // a FileList, exactly like input.files
    for (var i = 0; i < files.length; i++) {
        upload(files[i]);
    }
});

Forgetting e.preventDefault() on dragover is the classic mistake. The default action is "open this file", so the browser navigates away from your page and displays the image. The drop handler never runs and it looks like your code is broken.

Dropping whole folders

Chromium and WebKit browsers expose a directory entry API that lets you walk a dropped folder recursively:

var items = e.dataTransfer.items;

for (var i = 0; i < items.length; i++) {
    var entry = items[i].webkitGetAsEntry && items[i].webkitGetAsEntry();
    if (entry && entry.isDirectory) {
        readDirectory(entry);   // recurse with a directory reader
    }
}

Support is uneven and the reader is asynchronous and batched, which makes correct recursion fiddly. This is one of the better reasons to use a library rather than hand-roll.

Pasting from the clipboard

The same File objects arrive on a paste, which is how users expect to attach a screenshot:

document.addEventListener("paste", function (e) {
    var items = e.clipboardData && e.clipboardData.items;
    for (var i = 0; i < items.length; i++) {
        if (items[i].kind === "file") {
            upload(items[i].getAsFile());
        }
    }
});

Doing it in one line with ASP Uploader

Everything above is worth understanding, but you do not have to write it. Point DropZoneID at any element and the uploader wires dragover, dragenter and drop on it for you, handing the dropped files to the same queue the browse button feeds:

<div id="mydropzone">
    <%
    Dim uploader
    Set uploader = new AspUploader
    uploader.Name = "myuploader"
    uploader.MultipleFilesUpload = true
    uploader.AllowedFileExtensions = "*.jpg,*.png,*.gif,*.zip"

    ' any element id - the panel, the form, the whole page
    uploader.DropZoneID = "mydropzone"
    %>
    <%= uploader.GetString() %>
</div>

Dropped files are validated, queued, and reported on exactly like picked ones, and they arrive on the server through the same GetUploadedFile call. There is a live demo of it.

Two things it does not do. The uploader takes the drop but applies no styling, so the hover state is yours to write — see the CSS above. And it reads dataTransfer.files, which does not descend into directories, so dropping a folder still needs the directory-entry API covered earlier.

Worth knowing either way: a standard <input type="file"> accepts a file dropped directly onto the input itself, with no JavaScript at all.

<%@ Language="VBScript" %>
<!-- #include file="aspuploader/include_aspuploader.asp" -->

<form id="form1" method="POST">
    <%
    Dim uploader
    Set uploader = new AspUploader
    uploader.Name = "myuploader"
    uploader.MultipleFilesUpload = true
    uploader.MaxSizeKB = 10240
    uploader.InsertText = "Choose files"
    uploader.AllowedFileExtensions = "*.jpg,*.png,*.gif,*.pdf"
    %>
    <%= uploader.GetString() %>
</form>

Server-side handling is identical either way — by the time the file reaches ASP, nothing records whether it was dropped or picked from a dialog:

<%
If Request.Form("myuploader") & "" <> "" Then
    Dim list, i, mvcfile
    list = Split(Request.Form("myuploader"), "/")
    For i = 0 To UBound(list)
        Set mvcfile = uploader.GetUploadedFile(list(i))
        mvcfile.MoveTo Server.MapPath("uploads/" & mvcfile.FileName)
    Next
End If
%>

Designing a drop zone people can use

  • Make it look droppable before anything is dragged. A dashed border and an explicit "drop files here" label. Invisible affordances get used by nobody.
  • Give strong hover feedback. Change the border and background on dragover. Users need to know the drop will land.
  • Make the zone generous. A 40-pixel strip is a precision task; a large panel is not.
  • Always keep the browse button. Drag and drop is impossible on touch devices and hard with assistive technology. It is an accelerator, never the only route.
  • Handle a drop of the wrong type gracefully. Dropping a 4 GB video onto a "profile picture" zone should say so immediately, not start transferring.
#dropzone {
    border: 2px dashed #c9d2e3;
    border-radius: .5rem;
    padding: 2.5rem;
    text-align: center;
    color: #5a6b8c;
    transition: background .15s, border-color .15s;
}

#dropzone.is-over {
    border-color: #377dff;
    background: #f4f8ff;
}

Accessibility

Drag and drop cannot be performed with a keyboard, so the file input must remain reachable and labelled. Keep the real <input type="file"> in the DOM — visually hidden is fine, display:none is not — and announce queue changes in a live region so screen reader users hear that a file was added.

Frequently asked questions

Does drag and drop upload work in all browsers?

All current desktop browsers support dropping files onto a page, and onto a <input type="file"> directly. Folder dropping is limited to Chromium and WebKit based browsers. Touch devices have no drag and drop at all, so a browse button must always remain.

Can I drag files from one browser window to another?

No. Only files dragged from the operating system's file manager produce real File objects.

Does drag and drop require a plug-in?

No. It is native HTML5 — Flash and Silverlight have not been needed for this in over a decade.

Does ASP Uploader provide a drop zone out of the box?

Yes. Set DropZoneID to the id of any element and the uploader wires the drag events on it, so dropped files join the queue like picked ones. The hover styling is still yours to write, and dropping a folder is not supported — only files.

Skip the plumbing

ASP Uploader does everything on this page out of the box: multi-file selection, a real progress bar, client and server validation, incremental large-file handling, and no COM component to register. Drop the folder on your server and add one include line.

Download the free trial Try the live demo Pricing