如何从输入文件控件中删除一个特定的选定文件?
我有一个输入文件控件,可以选择多个文件;但是,我想验证一个文件,如果它的扩展名错误,那么我应该从文件控件本身中删除该文件,这可能吗?
我尝试如下
<input type="file" name="fileToUpload" id="fileToUpload" multiple/>
<script> $("#fileToUpload")[0].files[0] </script>
下面是对象的屏幕截图,但我无法修改它
如何从输入文件控件中删除一个特定的选定文件?
我有一个输入文件控件,可以选择多个文件;但是,我想验证一个文件,如果它的扩展名错误,那么我应该从文件控件本身中删除该文件,这可能吗?
我尝试如下
<input type="file" name="fileToUpload" id="fileToUpload" multiple/>
<script> $("#fileToUpload")[0].files[0] </script>
下面是对象的屏幕截图,但我无法修改它
正如其他人指出的那样,FileList
是只读的。您可以通过将这些文件推送到单独的文件中来解决此问题Array
。然后,您可以使用该精选文件列表做任何您想做的事情。如果将它们上传到服务器是目标,您可以使用FileReader
API。
下面是一个完全避免需要修改FileList
. 脚步:
FileReader
API读取本地文件事件处理程序和基本文件循环代码:
var validatedFiles = [];
$("#fileToUpload").on("change", function (event) {
var files = event.originalEvent.target.files;
files.forEach(function (file) {
if (file.name.matches(/something.txt/)) {
validatedFiles.push(file); // Simplest case
} else {
/* do something else */
}
});
});
下面是一个更复杂的文件循环版本,展示了如何使用FileReader
API 将文件加载到浏览器中,并可选择将其作为 Base64 编码的 blob 提交到服务器。
files.forEach(function (file) {
if (file.name.matches(/something.txt/)) { // You could also do more complicated validation after processing the file client side
var reader = new FileReader();
// Setup listener
reader.onload = (function (processedFile) {
return function (e) {
var fileData = { name : processedFile.name, fileData : e.target.result };
// Submit individual file to server
$.post("/your/url/here", fileData);
// or add to list to submit as group later
validatedFiles.push(fileData);
};
})(file);
// Process file
reader.readAsDataURL(file);
} else {
/* still do something else */
}
});
FileReader
关于使用API的注意事项。Base64 编码文件将使其大小增加约 30%。如果这不可接受,您将需要尝试其他方法。
我想我也应该在这里添加我的评论(我已经在这里回答了:JavaScript delete File from FileList to be upload)
我找到了解决方法。这根本不需要 AJAX 请求,并且可以将表单发送到服务器。基本上,您可以创建一个hidden
或text
输入并将其value
属性设置为在处理所选文件后创建的 base64 字符串。
<input type=hidden value=${base64string} />
您可能会考虑创建多个输入文件而不是 inputtext
或hidden
. 这将不起作用,因为我们无法为其分配值。
此方法将在发送到数据库的数据中包含输入文件,并忽略输入文件,您可以:
disabled
在序列化表单之前将属性设置为输入文件;当您想删除文件时,只需获取元素的索引并从 DOM 中删除输入元素(文本或隐藏)。
要求:
change
每当输入文件触发事件时,您需要编写逻辑来转换 base64 中的文件并将所有文件存储在一个数组中。优点:
我知道这是一篇旧帖子,但我花了很长时间试图解决这个问题,所以我会发布我的解决方案。有一种方法可以用另一个 fileList 更新 fileField 元素的 fileList - 这可以通过 DataTransfer 完成:
let updateFileList = function (fileField, index) {
let fileBuffer = Array.from(fileField.files);
fileBuffer.splice(index, 1);
/** Code from: https://stackoverflow.com/a/47172409/8145428 */
const dT = new ClipboardEvent('').clipboardData || // Firefox < 62 workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655
new DataTransfer(); // specs compliant (as of March 2018 only Chrome)
for (let file of fileBuffer) { dT.items.add(file); }
fileField.files = dT.files;
}
上述函数将 fileField 作为一个 DOM 对象,将要删除的 fileField 的 fileList 中的文件索引,并相应地更新传递的 fileField。
希望这可以节省其他人一些时间!
基于@liamthorne4 的回答,这是一个在 Firefox 和 Chrome 上测试的上传、列出和删除列表中元素的工作解决方案:
HTML:
<button onclick="uploadFile(event)">Upload files</button>
<div id="listfiles" class="view_list"></div>
<input class="hidden" type="file" id="input_file_id" onchange="fileList(event)" name="files[]" multiple>
JS:
function uploadFile(evt) {
evt.preventDefault();
$('#input_file_id').click();
}
function fileList(e) {
var files = $('#input_file_id').prop("files");
var names = $.map(files, function(val) { return val.name; });
for (n in names) {
$("#listfiles").append("<div id=preload_"+n+" title='"+names[n]+"'><p>"+names[n]+"</p><a onclick=deleteFile("+n+")>Delete</a></div>");
}
}
function deleteFile(index) {
filelistall = $('#input_file_id').prop("files");
var fileBuffer=[];
Array.prototype.push.apply( fileBuffer, filelistall );
fileBuffer.splice(index, 1);
const dT = new ClipboardEvent('').clipboardData || new DataTransfer();
for (let file of fileBuffer) { dT.items.add(file); }
filelistall = $('#input_file_id').prop("files",dT.files);
$("#preload_"+index).remove()
}
html
<input id="fileInput" name="fileInput" type="file" />
<input onclick="clearFileInput()" type="button" value="Clear" />
javascript
function clearFileInput(){
var oldInput = document.getElementById("fileInput");
var newInput = document.createElement("input");
newInput.type = "file";
newInput.id = oldInput.id;
newInput.name = oldInput.name;
newInput.className = oldInput.className;
newInput.style.cssText = oldInput.style.cssText;
// copy any other relevant attributes
oldInput.parentNode.replaceChild(newInput, oldInput);
}