我使用类似于this answer的代码通过ajax实现了文件下载按钮。我的代码看起来像这样:
$('#download-link').on('click', function (event) {
event.preventDefault();
var link = $('#download-link').attr('href');
$.ajax({
url: link,
success: function (result) {
var blob = getBlob(result);
var a = document.createElement('a');
var url = (window.URL ? URL : webkitURL).createObjectURL(blob);
a.href = url;
a.download = 'somefilename.txt';
a.style.display = 'none';
document.body.appendChild(a);
try {
a.click();
}
catch (err) {
//fallback. if .click() is unavailable display a new button for user to get file.
a.style.display = '';
a.innerText = 'Get File';
var downloadButton = document.getElementById('download-link');
downloadButton.style.display = 'none';
}
}
});
});
基本上,我们正在创建一个对象URL,使用对象URL的Href创建一个<a>
元素,并在该元素上调用Click()
来下载该文件。有些浏览器会在此时抛出错误,因此作为后备,我们会捕获错误并显示创建的按钮,以便用户可以按下并获取文件。
问题是某些浏览器(似乎在iOS上,而旧版本的Android)会忽略Click()
调用。我知道我可以使用浏览器嗅探来解决这个问题,但我不认为这是一个非常好的解决方案。我能做些更优雅的事情来发现这种情况并使用我的后备吗?
答案 0 :(得分:2)
您可以创建一个标志来检查您的脚本是否能够触发click事件。听取点击并翻转标志,并在一段时间后处理没有检测到点击的情况。
a.href = url;
a.download = 'somefilename.txt';
a.style.display = 'none';
var linkClicked = false;
a.addEventListener('click',()=>linkClicked = true);
document.body.appendChild(a);
a.click();
setTimeout(()=>{
if(!linkClicked){
//fallback. if .click() is unavailable display a new button for user to get file.
a.style.display = '';
a.innerText = 'Get File';
var downloadButton = document.getElementById('download-link');
downloadButton.style.display = 'none';
}
},500);
另一个解决方案是始终显示链接,但链接文本就行了#34;如果您的下载没有开始,请点击此处&#34;
答案 1 :(得分:0)
@Professor Allman已经通过检测.click()
功能提供了一个优雅的解决方案,而不是嗅探浏览器。
为了使代码更易于使用,我想重构代码,添加缓存并将其包装为单个函数:
function hasClickFeature(callback) {
if (window.hasAnchorClickFeature !== undefined) {
callback(window.hasAnchorClickFeature);
}
var a = document.createElement('a');
var hasClick = false;
a.href='javascript:;';
a.style.display = 'none';
a.addEventListener('click', function() {
hasClick = true;
window.hasAnchorClickFeature = hasClick;
callback(hasClick);
});
document.body.appendChild(a);
a.click();
setTimeout(function() {
if (!hasClick) {
window.hasAnchorClickFeature = hasClick;
callback(hasClick);
}
}, 500);
}
hasClickFeature(function(hasClick) {
console.log(hasClick);
});