Skip to content

Dragging <a href="blob:..." download> should include a File in the drag data store #12387

@janez-resnik

Description

@janez-resnik

What problem are you trying to solve?

Web apps increasingly generate files client-side (JSON exports, CSV reports, images) using Blob URLs. Transferring these to another page's file upload requires downloading to disk first, then dragging from the downloads bar — cluttering the filesystem for transient data. The natural gesture — drag the download link into an upload box — should just work, but currently the drag only carries a URL, not a File.

What solutions exist today?

  • Download then drag: User clicks the link to download, then drags from the downloads bar into the upload box. Two steps, leaves files on disk.
  • Chrome-only DownloadURL: e.dataTransfer.setData('DownloadURL', 'mime:name:url') in a dragstart handler. Only works in Chrome, requires a real HTTP URL (not blob: or data:), and has been progressively restricted.
  • Clipboard: navigator.clipboard.writeText() on the source page, paste handler on the target page. Requires control of both pages, struggles with large payloads (10MB+), and is a copy-paste UX rather than drag-and-drop.

How would you solve it?

When a user drags an <a> element that has both a download attribute and a blob: or data: href, the browser automatically includes a File entry in the drag data store, alongside the existing text/uri-list and text/plain entries. The filename comes from the download attribute value. The MIME type comes from the Blob's type.

  • data: URLs: The browser does not expose the raw data: URL to the drop target. Instead, on dragstart it reserves a blob: URL scoped to the source page's origin. The text/uri-list entry contains this blob: URL. Actual decoding can be deferred until the drop target reads dataTransfer.files or fetches the blob: URL. This avoids URL length issues and unifies both schemes.
  • Timing: The browser determines whether to include a File entry based on the element's download attribute and href scheme at the time the drag is initiated, before dragstart fires. Modifications to the element during dragstart do not affect the drag data store.
  • No new JS API: The browser populates the File, not page script. JS dragstart handlers cannot replace or remove the browser-generated File. What you drag is exactly what a click would download.
  • Opt-in/out: The download attribute is the opt-in. Removing it restores current behavior. No new events, flags, or cancellation mechanisms are required.
  • Backward compatible: Drop targets that only look for URLs still get URLs. Drop targets that check for files now also work. Nothing breaks.
  • Memory: The File entry references the existing Blob — no copy required. If a blob: URL is revoked during drag, the drop fails gracefully.

Anything else?

  • Scope: Limited to blob: and data: URLs. HTTP(S) URLs are excluded because they'd require a network fetch on dragstart.
  • data: backward compatibility: <a href="data:..." download> has no reliable behavior in current browsers (the download attribute is largely ignored for data: URLs due to their opaque origin), so there is no backward compatibility risk.
  • Cross-origin: The blob: URL created for a data: href is scoped to the source page's origin. Cross-origin drop targets should use dataTransfer.files rather than the URL.
  • Security: The browser already trusts this content enough to write it to disk on click — including a File in the drag data store is no more privileged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    addition/proposalNew features or enhancementsneeds implementer interestMoving the issue forward requires implementers to express interest

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions