在页面上删除文件时如何设置文件输入值? [重复]

时间:2021-07-22 03:31:30

This question already has an answer here:

这个问题在这里已有答案:

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 JavaScript without additional libraries.

正如您从MCVE中看到的,我只对使用jQuery或纯JavaScript而不使用其他库感兴趣。

Although dropzone.js could be used, it doesn't fit in my requirements and it would require a considerate amount of time to customize its look. Moreover, dropzone.js have 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?

有一个类似的问题,但没有一个正确的答案:如何将文件对象设置为HTML格式的输入文件?

Also not similar to drag drop images input file and preview before upload because 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.

因为我已经实现了拖放和预览操作,所以在上传之前也没有类似于拖放图像输入文件和预览。我的问题是特定于在父容器中删除文件时输入空文件的问题。

1 个解决方案

#1


25  

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

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


TL;DR: Yes, now you can!

*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.

以前,由于旧的安全漏洞(在现代浏览器上已修复),以编程方式更改文件输入[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引用的相关屏幕截图和文字:

在页面上删除文件时如何设置文件输入值? [重复]

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

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

The Firefox bugfix discussion thread has this demo you can test it 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错误修正讨论线程有这个演示,您可以测试它,如果您想编辑它,这里是源。如果此链接死亡以供将来参考,我还将其包含在下面的runnable片段中:

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 FileList OR dataTransfer object that you are able to set to the input file element (as the setter method DOES NOT accept plain text strings).

只有当您具有可以设置为输入文件元素的现有FileList OR dataTransfer对象时,才能执行此操作(因为setter方法不接受纯文本字符串)。

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?

有关详细信息,请参阅Kaiido的答案:如何在FileList对象中设置File对象和length属性,其中文件也反映在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;
    });

#1


25  

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

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


TL;DR: Yes, now you can!

*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.

以前,由于旧的安全漏洞(在现代浏览器上已修复),以编程方式更改文件输入[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引用的相关屏幕截图和文字:

在页面上删除文件时如何设置文件输入值? [重复]

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

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

The Firefox bugfix discussion thread has this demo you can test it 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错误修正讨论线程有这个演示,您可以测试它,如果您想编辑它,这里是源。如果此链接死亡以供将来参考,我还将其包含在下面的runnable片段中:

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 FileList OR dataTransfer object that you are able to set to the input file element (as the setter method DOES NOT accept plain text strings).

只有当您具有可以设置为输入文件元素的现有FileList OR dataTransfer对象时,才能执行此操作(因为setter方法不接受纯文本字符串)。

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?

有关详细信息,请参阅Kaiido的答案:如何在FileList对象中设置File对象和length属性,其中文件也反映在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;
    });