在 JavaScript 中以编程方式设置文件输入

2023-12-19 23:00:37 浏览数 (1)

设置文本或数字输入字段的值非常简单,只需执行以下操作:

代码语言:javascript复制
const input = document.querySelector('input');
input.value = '新值';

但是,对于文件输入字段,情况略有不同。与文本或数字字段不同,简单地设置文件输入字段的值是无效的。

当用户手动选择文件时,文件输入字段的值如下所示:

代码语言:javascript复制
input.addEventListener('change', (event) => {
  console.log(event.target.value);
  // => C:\fakepath\file.txt
});

常见的误解和尝试

用户系统中文件路径 C:fakepathfile.txt 在浏览器中是被隐藏的,设置值属性为其他值不会有任何区别,因为浏览器不依赖输入的值来获取文件的引用。在幕后,浏览器在用户磁盘上保留了文件的内部引用,但这并不对 DOM 可见,也不应更改。但你可以通过在输入元素上编程设置文件属性来修改文件。

不,这并不像以下这么简单:

代码语言:javascript复制
const file = '路径/到/我的文件.ext';
input.files = file;

// 或者

input.files[0] = file;

或者创建一个文件对象并将其分配给 files0。

代码语言:javascript复制
const myFile = new File(['我的文件内容'], 'my_file.txt');

input.files[0] = myFile; // 不起作用

input.files = [myFile]; // 不起作用

以上尝试也不会生效,因为 files 对象是 FileList 接口的一种类型,它不是内部数组,而是类似数组的对象。可以在 w3c 规范中查看。

我的方法

在寻找答案时,我在 Stackoverflow 上得到了一堆不赞同的回答和否定。有一个答案告诉 PHP 用户,如果有解决方法,它最终会被 Chrome 构建者禁用。然而,这与此处的解决方案不同,因为要禁用此功能将意味着禁用拖放功能模拟(在大多数测试库中使用),自定义拖放交互或自定义剪贴板操作。这个解决方案是基于拖放功能的。

以下是解决方案:

代码语言:javascript复制
const fileInput = document.querySelector('input[type="file"]');

// 准备好你的文件
const myFileContent = ['我的文件内容'];
const myFileName = 'my_file.txt';
const myFile = new File(myFileContent, myFileName);

// 创建数据传输对象。类似于 `drop` 事件中的 `event.dataTransfer`
const dataTransfer = new DataTransfer();

// 将文件添加到对象的文件列表中
dataTransfer.items.add(file);

// 将文件列表保存到一个新变量中
const fileList = dataTransfer.files;

// 将输入的 `files` 设置为文件列表
fileInput.files = fileList;

根据你的使用情况,你可以触发一个 change 和/或 input 事件以模拟实际用户交互:

代码语言:javascript复制
fileInput.dispatchEvent(new Event('change', { bubbles: true }));

// 和/或

fileInput.dispatchEvent(new Event('input', { bubbles: true }));

在我的情况下,我遇到了一个问题,我需要更改表单中文件输入字段的文件内容,但我无法访问代码。表单的底层代码会监视文件输入更改或 dragover/drop JavaScript 事件。这个解决方案帮助我完美地模拟了用户交互,希望它对你的用例也有帮助。

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

0 人点赞