Skip to content

Commit ce3d4d8

Browse files
jooneJoone Hur
andauthored
[DownloadURL] add the explainer (#1122)
Co-authored-by: Joone Hur <joonehur@microsoft.com>
1 parent 976eed8 commit ce3d4d8

3 files changed

Lines changed: 216 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
name: DownloadURL
3+
about: new issue
4+
title: "[DownloadURL] <TITLE HERE>"
5+
labels: DownloadURL
6+
assignees: joone
7+
8+
---
9+
10+

DownloadURL/explainer.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# Explainer: Drag Multiple Virtual Files Out of Browser
2+
3+
Author: [Joone Hur](https://github.com/joone)
4+
5+
# Participate
6+
7+
- [Issue tracker](https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/DownloadURL)
8+
9+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
10+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
11+
# Table of Contents
12+
13+
- [Introduction](#introduction)
14+
- [Goals](#goals)
15+
- [Non-goals](#non-goals)
16+
- [Problem: The Single-File Limitation](#problem-the-single-file-limitation)
17+
- [Example of Current Behavior](#example-of-current-behavior)
18+
- [Developer Workarounds and Limitations](#developer-workarounds-and-limitations)
19+
- [Using an array](#using-an-array)
20+
- [Using newline-delimiters](#using-newline-delimiters)
21+
- [UX perspective](#ux-perspective)
22+
- [Proposed Solution: Extending the `DownloadURL` Data Format](#proposed-solution-extending-the-downloadurl-data-format)
23+
- [New `DownloadURL` Data Format](#new-downloadurl-data-format)
24+
- [Why JSON?](#why-json)
25+
- [Backward Compatibility](#backward-compatibility)
26+
- [Future Considerations](#future-considerations)
27+
- [Security & UX Considerations](#security--ux-considerations)
28+
- [Drag Bomb](#drag-bomb)
29+
- [Limit Download Requests](#limit-download-requests)
30+
- [Single-click button to delete all downloaded files](#single-click-button-to-delete-all-downloaded-files)
31+
- [Acknowledgements](#acknowledgements)
32+
- [Referenecs](#referenecs)
33+
34+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
35+
36+
# Introduction
37+
38+
Chromium has supported a non-standard drag type (`DownloadURL`) that allows Windows users to drag a virtual file out of the browser. However, the `DownloadURL` drag type is limited to supporting only a single file per drag-and-drop operation. To support more robust workflows, we propose extending the DownloadURL drag type to allow multiple files to be dragged simultaneously.
39+
40+
# Goals
41+
42+
Enable users to drag multiple files from Chromium to a desktop folder on Windows using an extended `DownloadURL` drag type.
43+
44+
# Non-goals
45+
This proposal does not aim to:
46+
* Enable drag-and-drop of files into other browser contexts, whether between the same browser or different browsers.
47+
* Standardize this behavior across browsers via W3C. The proposal is specific to Chromium and Windows environments.
48+
49+
# Problem: The Single-File Limitation
50+
The current DownloadURL drag type in Chromium supports only a single file per drag-and-drop operation, which restricts more advanced workflows and user experiences.
51+
52+
## Example of Current Behavior
53+
Here's a typical example demonstrating the limitation:
54+
55+
```js
56+
document.getElementById('downloadLink').addEventListener('dragstart', function(e) {
57+
// Define the file's MIME type, name, and URL
58+
const mimeType = 'application/pdf';
59+
const fileName = 'example.pdf';
60+
const fileUrl = 'https://example.com/files/example.pdf';
61+
62+
// Construct the downloadURL string
63+
const downloadUrlString = `${mimeType}:${fileName}:${fileUrl}`;
64+
65+
// Set the data on the DataTransfer object
66+
e.dataTransfer.setData('DownloadURL', downloadUrlString);
67+
});
68+
```
69+
The `DownloadURL` format requires a string with three colon-separated components:
70+
71+
- **MIME type:** The media type of the file (e.g., `image/jpeg`, `application/pdf`).
72+
73+
- **File name:** The desired name for the downloaded file (e.g., `my_document.pdf`).
74+
75+
- **URL:** The absolute URL from which the file will be downloaded, either remote or a data URI.
76+
77+
78+
When [it was initially proposed](https://lists.whatwg.org/pipermail/whatwg-whatwg.org/2009-August/022121.html), it was designed for single-file use. Although multi-file support was requested, it has never been implemented.
79+
80+
## Developer Workarounds and Limitations
81+
Because `DownloadURL` is a Chromium-specific feature and not part of any web standard, documentation is limited. As a result, developers have attempted to pass multiple files using arrays or newline-delimited strings, but these formats are not supported by the current implementation:
82+
83+
### Using an array
84+
```js
85+
event.dataTransfer.setData('DownloadURL', [
86+
'image/png:file1.png:http://foo.com/file1.png',
87+
'image/png:file2.png:http://foo.com/file2.png'
88+
]);
89+
90+
```
91+
92+
### Using newline-delimiters
93+
```js
94+
event.dataTransfer.setData("DownloadURL", "application/pdf:file1.pdf:https://example.com/file1.pdf\napplication/pdf:file2.pdf:https://example.com/file2.pdf");
95+
```
96+
Naturally, neither approach works as intended.
97+
98+
These limitations are discussed on Stack Overflow:
99+
* [Drag out multiple files from browser to desktop using event.dataTransfer.setData](https://stackoverflow.com/questions/42335222/drag-out-multiple-files-from-browser-to-desktop-using-event-datatransfer-setdata)
100+
* [Download multiple files with drag and drop to folder](https://stackoverflow.com/questions/79448045/download-multiple-files-with-drag-and-drop-to-folder)
101+
102+
## UX perspective
103+
104+
This single-file constraint presents a significant inconvenience for users who frequently interact with web applications that involve multiple downloadable items. For example, users are forced to perform multiple drag-and-drop operations for each file when trying to:
105+
* Download multiple email attachments from a webmail client (e.g., Outlook Web) to a desktop folder via a single drag gesture.
106+
* Export multiple generated reports or images from a web-based tool.
107+
108+
The current implementation forces users to perform multiple drag-and-drop operations for each file, which is inefficient and cumbersome.
109+
110+
# Proposed Solution: Extending the `DownloadURL` Data Format
111+
112+
To enable multi-file drag-and-drop, we propose extending the format of the `DownloadURL` drag type within the HTML Drag and Drop API to carry information for multiple files.
113+
114+
## New `DownloadURL` Data Format
115+
The `DownloadURL` data format will be extended to support an array of a file URL, serialized as a JSON string. Each object within this JSON array will represent a single file, containing its essential properties: `mimeType`, `filename`, and `url`.
116+
117+
**Example JavaScript Implementation:**
118+
```js
119+
function dragstart(event) {
120+
// JSON object for multiple files drag-and-drop.
121+
const data = [
122+
{
123+
'type': 'image/png',
124+
'name': 'file2.png',
125+
'url': 'http://example.com/file2.png'
126+
},
127+
{
128+
'type': 'image/jpeg',
129+
'name': 'file1.jpg',
130+
'url': 'http://example.com/file1.jpg'
131+
}
132+
];
133+
event.dataTransfer.setData('DownloadURL', JSON.stringify(data));
134+
}
135+
```
136+
137+
This new format allows a single `DownloadURL` data type to represent multiple files in a structured and extensible manner.
138+
139+
## Why JSON?
140+
141+
As seen in the examples of developer attempts, we could use a simple format to represent multiple files. However, the existing format requires its own parsing code, and there's always a risk of parsing errors due to user mistakes or security attacks. Therefore, JSON will be used for the new format because it is structured, extensible, widely supported, and robust.
142+
143+
# Backward Compatibility
144+
145+
A crucial aspect of this proposal is to maintain backward compatibility with the existing `DownloadURL` single-file format. The `DownloadURL` drag type will continue to support the existing colon-delimited string format (e.g., `mime-type:file_name:URL`) alongside the new JSON array format.
146+
147+
# Future Considerations
148+
149+
The `DownloadURL` drag type was originally implemented in WebKit([bug 31090](https://bugs.webkit.org/show_bug.cgi?id=31090)) and was later adopted by Chromium. However, it never standardized—primarily because it didn’t gain support in Gecko([bug 570164](https://bugzilla.mozilla.org/show_bug.cgi?id=570164)), where it was treated as a Chrome-specific mechanism
150+
151+
We can find a standard way to support dragging virtual files or file URLs out of browsers. While we could use `DataTransferItemList` to set multiple URL items, and the browser could download them when dragged to the desktop, the `text/uri-list` format used for this is an older standard that only carries URL information. This is insufficient for our needs, as it doesn't support additional details like the MIME type or desired filename. Therefore, to provide this richer download information, we would need to define a new drag format for downloading, potentially using the `application/json` MIME type.
152+
153+
```js
154+
function dragstart(event) {
155+
// Define the list of files to be dragged.
156+
const filesToDownload = [
157+
{
158+
"downloadUrl": "http://example.com/file1.jpg",
159+
"name": "image_one.jpg",
160+
"mimeType": "image/jpeg"
161+
},
162+
{
163+
"downloadUrl": "http://example.com/file2.png",
164+
"name": "image_two.png",
165+
"mimeType": "image/png"
166+
}
167+
];
168+
169+
// Add each file as a separate JSON item to the DataTransferItemList.
170+
for (const file of filesToDownload) {
171+
const jsonString = JSON.stringify(file);
172+
event.dataTransfer.items.add(jsonString, "application/json");
173+
}
174+
}
175+
```
176+
177+
# Security & UX Considerations
178+
179+
There was already a discussion in [the design document](https://docs.google.com/document/d/1nHPDuEE876RMKwYBVzWgPvsek-9X1NhZuFyY5Q5Z6YU/edit?usp=sharing) about security and UX concerns. Here is a summary of that discussion.
180+
181+
## Drag Bomb
182+
183+
After a user drags and drops a file, the Chrome/Edge browser shows a download bubble as a single row to indicate which file is being downloaded. When supporting multiple downloads, however, allowing a separate row for each file could enable a "drag bomb" attack, which clutters the UI and could conceal malicious items.
184+
185+
To prevent this, the download bubble will consolidate multiple downloads into a single row. For example, it would show: `file1.png, file2.png, ... (4)`, where the number in parentheses indicates the total count of downloaded files. This approach provides a safer and more streamlined experience for the user.
186+
187+
## Limit Download Requests
188+
189+
If the user does not consent to multiple downloads, the entire set of dragged files should be reverted. To ensure a smooth user experience, it is advisable to request consent in advance rather than prompting after each individual download.
190+
191+
## Single-click button to delete all downloaded files
192+
193+
A single-click option should be provided in the Chrome UI (download bubble and `chrome://downloads`) to allow users to easily remove all downloaded files from their device if they no longer want them or downloaded them by mistake.
194+
195+
# Acknowledgements
196+
Thank you to Daniel Cheng, Lily Chen, Lingling Becker, Mike Jackson, Min Qin for their valuable feedback and input.
197+
198+
# Referenecs
199+
* [Design: Enabling Multi‑File Drag‑and‑Drop in Chromium on Windows](https://docs.google.com/document/d/1nHPDuEE876RMKwYBVzWgPvsek-9X1NhZuFyY5Q5Z6YU/edit?usp=sharing)
200+
* [Chromium Issue](https://issues.chromium.org/issues/40736398)
201+
* [[whatwg] Proposal to drag virtual file out of browser](https://lists.whatwg.org/pipermail/whatwg-whatwg.org/2009-August/022121.html)
202+
* [HTML Drag and Drop API \- Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)
203+
* [Ryan Seddon | Drag out files like Gmail](https://ryanseddon.com/html5/gmail-dragout/)
204+
* [HTML Standard: 6.11 Drag and drop](https://html.spec.whatwg.org/multipage/dnd.html)
205+
* [Case Study \- Drag and Drop Download in Chrome | web.dev](https://web.dev/case-studies/box-dnd-download)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ These are proposals that are still really early in their lifecycle. We might jus
108108
| [Event Phases For Reliably Fast DOM Operations](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/EventPhases/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/EventPhases">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/EventPhases?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=slightlyoff&labels=EventPhases&title=%5BEventPhases%5D+%3CTITLE+HERE%3E) | Web Perf |
109109
| [Delayed Messages API](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/DelayedMessages/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/DelayedMessages">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/DelayedMessages?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=joone&labels=DelayedMessages&title=%5BDelayedMessages%5D+%3CTITLE+HERE%3E) | Web Perf |
110110
| [Back to Opener: Seamless Back Navigation in New Tabs](BackToOpener/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/BackToOpener">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/BackToOpener?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=victorhuangwq&labels=BackToOpener&title=%5BBackToOpener%5D+%3CTITLE+HERE%3E) | WHATWG |
111+
| [Drag Multiple Virtual Files Out of Browser](https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/DownloadURL/explainer.md) | <a href="https://github.com/MicrosoftEdge/MSEdgeExplainers/labels/DownloadURL">![GitHub issues by-label](https://img.shields.io/github/issues/MicrosoftEdge/MSEdgeExplainers/DownloadURL?label=issues)</a> | [New Issue...](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=joone&labels=DownloadURL&title=%5BDownloadURL%5D+%3CTITLE+HERE%3E) | N/A |
111112

112113
# Alumni 🎓
113114

0 commit comments

Comments
 (0)