我尝试使用在不同位置描述的黑客使用:
document.body.onfocus = checkOnCancel();
一个例子:
var fileSelectEle = document.getElementById('fileinput');
fileSelectEle.onclick = charge;
function charge()
{
document.body.onfocus = checkOnCancel;
}
function checkOnCancel()
{
alert("FileName:" + fileSelectEle.value + "; Length: " + fileSelectEle.value.length);
if(fileSelectEle.value.length == 0) alert('You clicked cancel!')
else alert('You selected a file!');
document.body.onfocus = null;
}
这里有什么不对吗?因为fileSelectedEle.value
始终返回先前的执行值而不是用户选择的值。
这是输入文件的预期行为吗?如何解决此问题以阅读所选的实际文件?
您可以通过以下方式重现错误:
步骤1:SelectFile - 一些选择一些文件(并注意输出)
步骤2:选择文件 - 按取消(并注意输出)
答案 0 :(得分:10)
一种解决方案是使用onchange
的{{1}}事件。
input
这可以正确响应所选文件名中的更改,因为您可以在此处测试:http://jsfiddle.net/munderwood/6h2r7/1/
与您尝试执行此操作的方式唯一不同的是,如果您立即取消,或连续两次取消,或连续两次选择相同的文件,则该事件将不会触发。但是,每次文件名实际更改时,您都会正确检测到它。
我不确定为什么你的原始尝试不起作用,尽管我最好的猜测是var fileSelectEle = document.getElementById('fileinput');
fileSelectEle.onchange = function ()
{
if(fileSelectEle.value.length == 0) {
alert('You clicked cancel - ' + "FileName:" + fileSelectEle.value + "; Length: " + fileSelectEle.value.length);
} else {
alert('You selected a file - ' + "FileName:" + fileSelectEle.value + "; Length: " + fileSelectEle.value.length);
}
}
事件异步触发,在onfocus
控件的属性之前是时间问题已完成更新。
更新:要确定用户每次关闭文件对话框时选择的内容,即使没有任何更改,也可以通过在再次接收焦点之间添加短暂延迟来避开时间问题,检查文件输入的值。以下版本的input
不会在收到焦点后立即调用checkOnCancel
,而是会在之后的十分之一秒内调用它。
charge
这是一个有效的版本:http://jsfiddle.net/munderwood/6h2r7/2/。
答案 1 :(得分:0)
这里有什么不对吗?因为fileSelectedEle.value始终返回先前的执行值而不是用户选择的值。这是输入文件的预期行为吗?如何解决此问题以读取所选的实际文件?
没有错,这是预期的行为。如果用户取消了文件选择过程,那么它就好像从未启动它一样。因此,之前的值保留不变。
答案 2 :(得分:0)
您可以挂钩window.focus
事件,当它们取消窗口的文件选择框时会被触发。然后检查它是否确实选择了文件。
答案 3 :(得分:0)
//此代码在chrome中适用于文件选择,请尝试
<--write this line in HTML code-->
<input type='file' id='theFile' onclick="initialize()" />
var theFile = document.getElementById('theFile');
function initialize() {
document.body.onfocus = checkIt;
console.log('initializing');
}
function checkIt() {
setTimeout(function() {
theFile = document.getElementById('theFile');
if (theFile.value.length) {
alert('Files Loaded');
} else {
alert('Cancel clicked');
}
document.body.onfocus = null;
console.log('checked');
}, 500);
}
答案 4 :(得分:0)
处理用户可以取消文件输入的所有各种方式变得很棘手。
window.focus
事件来检测他们何时回来,而无需选择任何东西来检测取消window.touchend
来检测这一点实现明智,您可以使用 addEventListener
来确保您不会替换可能已经在窗口上的其他事件侦听器 - 并在触发后轻松清理事件侦听器。例如:
window.addEventListener('focus', () => console.log('no file selected'), { once: true });
下面是一个示例,说明如何使用它以编程方式获取图像,处理上面列出的注意事项(打字稿):
/**
* opens the user OS's native file picker, returning the selected images. gracefully handles cancellation
*/
export const getImageFilesFromUser = async ({ multiple = true }: { multiple?: boolean } = {}) =>
new Promise<File[]>((resolve) => {
// define the input element that we'll use to trigger the input ui
const fileInput = document.createElement('input');
fileInput.setAttribute('style', 'visibility: hidden'); // make the input invisible
let inputIsAttached = false;
const addInputToDom = () => {
document.body.appendChild(fileInput); // required for IOS to actually fire the onchange event; https://stackoverflow.com/questions/47664777/javascript-file-input-onchange-not-working-ios-safari-only
inputIsAttached = true;
};
const removeInputFromDom = () => {
if (inputIsAttached) document.body.removeChild(fileInput);
inputIsAttached = false;
};
// define what type of files we want the user to pick
fileInput.type = 'file';
fileInput.multiple = multiple;
fileInput.accept = 'image/*';
// add our event listeners to handle selection and canceling
const onCancelListener = async () => {
await sleep(50); // wait a beat, so that if onchange is firing simultaneously, it takes precedent
resolve([]);
removeInputFromDom();
};
fileInput.onchange = (event: any) => {
window.removeEventListener('focus', onCancelListener); // remove the event listener since we dont need it anymore, to cleanup resources
window.removeEventListener('touchend', onCancelListener); // remove the event listener since we dont need it anymore, to cleanup resources
resolve([...(event.target!.files as FileList)]); // and resolve the files that the user picked
removeInputFromDom();
};
window.addEventListener('focus', onCancelListener, { once: true }); // detect when the window is refocused without file being selected first, which is a sign that user canceled (e.g., user left window into the file system's file picker)
window.addEventListener('touchend', onCancelListener, { once: true }); // detect when the window is touched without a file being selected, which is a sign that user canceled (e.g., user did not leave window - but instead canceled the modal that lets you choose where to get photo from on ios)
// and trigger the file selection ui
addInputToDom();
fileInput.click();
});