Javascript 在页面上放置文件时如何设置文件输入值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47515232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:51:54  来源:igfitidea点击:

How to set file input value when dropping file on page?

javascriptjqueryformsfileevents

提问by Tristan

I'm attempting to make a control where you can both select a file to submit in the form and drop a file into it to do the same thing. I have something like this where it will also show a preview of the file if it's an image:

我正在尝试制作一个控件,您可以在其中选择要在表单中提交的文件并将文件放入其中以执行相同的操作。我有这样的东西,如果它是图像,它还会显示文件的预览:

<div class="preview-image-container">

  <input type="file" name="File" id="File" accept="image/*" 
         class="image-url form-control" style="display:none;" />

  <div class="preview-image-dummy"></div><img class="preview-image-url" />
  <div class="preview-image-instruction">
    <div class="preview-image-btn-browse btn btn-primary">Select file</div>
    <p>or drop it here.</p>
  </div>

</div>

Here's a fiddle with MCVE.

这是 MCVE 的小提琴

The user drops the file in the preview-image-container. The file isn't submitted with AJAX, the user needs to submit the form which contain more data.

用户将文件放入preview-image-container. 该文件不是用 AJAX 提交的,用户需要提交包含更多数据的表单。

For security reasons, we aren't allowed to change the value of the input file with JavaScript. However, I know that the default input file support droppable and there's a bunch of websites that let us select files by dropping them in the form so my guess is that there's a way to do it.

出于安全原因,我们不允许使用 JavaScript 更改输入文件的值。但是,我知道默认输入文件支持 droppable,并且有很多网站允许我们通过将文件放入表单中来选择文件,所以我猜有一种方法可以做到这一点。

As you can see from the MCVE, I am only interested in using jQuery or pure JavaScriptwithout additional libraries.

正如您从 MCVE 中看到的那样,我只对使用jQuery 或纯 JavaScript而没有附加库感兴趣。

Although dropzone.jscould be used, it doesn't fit in my requirements and it would require a considerate amount of time to customize its look. Moreover, dropzone.jshave certain configuration requirements that can't be met within my ASP.NET application.

虽然可以使用dropzone.js,但它不符合我的要求,并且需要相当长的时间来自定义其外观。此外,dropzone.js具有某些在我的 ASP.NET 应用程序中无法满足的配置要求。



There's a similar question but does not have a proper answer:
How to set file object into input file in the form in HTML?

有一个类似的问题,但没有正确答案:
How to set file object into input file in the form in HTML?

Also not similar to drag drop images input file and preview before uploadbecause I have already achieved drag-drop and preview action. My question is specific to the problem of having an empty file input when dropping the file in a parent container.

也不像拖放图片输入文件和上传前预览,因为我已经实现了拖放和预览动作。我的问题特定于将文件放入父容器时输入空文件的问题。

回答by Samuel Liew

Disclaimer: Correct as of December 2017 and for modern browsers only.

免责声明:截至 2017 年 12 月更正,仅适用于现代浏览器。



TL;DR: Yes, now you can!

TL;DR:是的,现在你可以了!

*if you have a dataTransfer or FileList object

*如果你有一个 dataTransfer 或 FileList 对象

Previously, programmatically changing the files input[type=file]field was disabled due to legacy security vulnerabilities, which are fixed on modern browsers.

以前input[type=file]由于遗留安全漏洞,以编程方式更改文件字段已被禁用,这些漏洞已在现代浏览器上修复。

The last of the major browsers (Firefox), has recently enabled us to set the files for the input file field. According to W3C testing, it seems that you can already do this on Google Chrome!

最后一个主要浏览器 (Firefox) 最近使我们能够为输入文件字段设置文件。根据W3C 测试,您似乎已经可以在 Google Chrome 上执行此操作!

Relevant screenshot and text quoted from MDN:

引用自 MDN 的相关截图和文字:

enter image description here

在此处输入图片说明

You can setas well as get the value of HTMLInputElement.filesin all modern browsers.
Source and browser compatibility, see MDN

您可以在所有现代浏览器中设置和获取值HTMLInputElement.files
源代码和浏览器兼容性,参见MDN

The Firefox bugfix discussionthread has this demo you can testit out on, and here's the source if you want to edit it. For future reference in case this link dies, I will also include it as a runnable snippet below:

Firefox 错误修复讨论线程有这个演示,您可以对其进行测试如果您想编辑它,这里是源代码。为了将来参考,以防此链接失效,我还将其作为可运行的代码段包含在下面:

let target = document.documentElement;
let body = document.body;
let fileInput = document.querySelector('input');

target.addEventListener('dragover', (e) => {
  e.preventDefault();
  body.classList.add('dragging');
});

target.addEventListener('dragleave', () => {
  body.classList.remove('dragging');
});

target.addEventListener('drop', (e) => {
  e.preventDefault();
  body.classList.remove('dragging');
  
  fileInput.files = e.dataTransfer.files;
});
body {
  font-family: Roboto, sans-serif;
}

body.dragging::before {
  content: "Drop the file(s) anywhere on this page";
  position: fixed;
  left: 0; width: 100%;
  top: 0; height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1.5em;
  background-color: rgba(255, 255, 0, .3);
  pointer-events: none;
}

button, input {
  font-family: inherit;
}

a {
  color: blue;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
      <link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700" rel="stylesheet"> 

  <title>JS Bin</title>
</head>
<body>
  
  <h1>Drag and drop files into file input</h1>
  
  <p><small>Supported in <a href="https://github.com/whatwg/html/issues/2861">WebKit and Blink</a>. To test, drag and drop one or more files from your operating system onto this page.</small></p>
  
  <p>
    <input type="file">
  </p>

</body>
</html>



Important note:

You can only do this if you have an existing FileListOR dataTransferobject that you are able to set to the input file element (as the setter method DOES NOT accept plain text strings).

For further information, see Kaiido's answer here: How to set File objects and length property at FileList object where the files are also reflected at FormData object?

重要的提示:

只有当您有一个可以设置为输入文件元素的现有FileListORdataTransfer对象时,您才能这样做(因为 setter 方法不接受纯文本字符串)。

有关更多信息,请参阅 Kaiido 在此处的回答:如何在 FileList 对象中设置文件对象和长度属性,其中文件也反映在 FormData 对象中?



Now to answer your original question, it should be as simple as this:

现在要回答你原来的问题,它应该像这样简单:

document.querySelector('.preview-image-instruction')
    .addEventListener('drop', (ev) => {
        ev.preventDefault();
        document.querySelector('.image-url').files = ev.dataTransfer.files;
    });