在页面上放置文件时如何设置文件输入值? [英] How to set file input value when dropping file on page?

查看:23
本文介绍了在页面上放置文件时如何设置文件输入值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<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">选择文件</div><p>或者把它放在这里.</p>

<块引用>

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

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

let target = document.documentElement;让 body = document.body;让 fileInput = document.querySelector('input');target.addEventListener('dragover', (e) => {e.preventDefault();body.classList.add('拖动');});target.addEventListener('dragleave', () => {body.classList.remove('拖动');});target.addEventListener('drop', (e) => {e.preventDefault();body.classList.remove('拖动');fileInput.files = e.dataTransfer.files;});

body {字体系列:Roboto,无衬线;}body.dragging::before {content: "将文件放在此页面的任何位置";位置:固定;左:0;宽度:100%;顶部:0;高度:100%;显示:弹性;对齐内容:居中;对齐项目:居中;字体大小:1.5em;背景颜色:rgba(255, 255, 0, .3);指针事件:无;}按钮,输入{字体系列:继承;}一种 {颜色:蓝色;}

<头><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><身体><h1>将文件拖放到文件输入端</h1><p><small>在 <a href="https://github.com/whatwg/html/issues/2861">WebKit 和 Blink</a> 中得到支持.要进行测试,请将一个或多个文件从您的操作系统拖放到此页面上.</small></p><p><输入类型=文件"></p></html>

<小时><块引用>

重要提示:

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

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

<小时>

现在回答你最初的问题,应该像这样简单:

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

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.

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.

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.

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

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.


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?

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.

解决方案

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


TL;DR: Yes, now you can!

*if you have a dataTransfer or FileList object

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

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!

Relevant screenshot and text quoted from MDN:

You can set as well as get the value of HTMLInputElement.files in all modern browsers.
Source and browser compatibility, see 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:

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

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?


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;
    });

这篇关于在页面上放置文件时如何设置文件输入值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆