macOS浏览器中文件输入的大小与内容无法更新问题求助
你遇到的这个问题确实和macOS的文件沙箱安全机制密切相关,并非单纯的浏览器bug。
问题根源
在macOS的安全模型中,当用户通过<input type="file">选择文件后,浏览器会获取该文件的静态快照引用,而不是实时绑定到文件本身。对于你提到的旧版本Safari(10.1.2)和Firefox(51.0.1),它们严格遵循了macOS的沙箱规则:
- 只有文件的元数据(比如
lastModified)会因为系统层面的变动被被动更新; - 但文件的
size和内容读取权限会被锁定在初始快照状态,浏览器无法自动获取文件修改后的新数据——因为这需要重新向系统请求文件访问权限,而旧版浏览器没有实现这个逻辑。
而Windows系统的浏览器采用了不同的文件访问模型,允许在用户授权一次后持续读取文件的最新状态,所以不会出现这个问题。
测试验证
你提供的代码可以完美复现这个问题:在macOS的目标浏览器中选择一个文本文件,修改文件内容并保存后,页面上的Size值会始终停留在初始大小,只有Last modified会更新。
可行解决方案
针对这个问题,根据你的兼容性需求,可以选择以下方案:
方案1:引导用户重新选择文件
这是最兼容旧浏览器的方式——当检测到lastModified变化但size未更新时,提示用户重新选择文件,让浏览器获取新的文件快照,从而读取最新内容和size。方案2:使用File System Access API(仅兼容现代浏览器)
如果你不需要支持过旧的浏览器版本,可以使用现代浏览器提供的File System Access API,它允许请求持续的文件访问权限,实时监听并读取文件的最新状态。示例代码如下:async function setupFileWatcher() { // 请求选择文件并获取文件句柄 const [fileHandle] = await window.showOpenFilePicker(); // 读取初始文件内容 const initialFile = await fileHandle.getFile(); console.log('初始文件大小:', initialFile.size); console.log('初始内容:', await initialFile.text()); // 监听文件变化 const watcher = await fileHandle.watch(async (event) => { if (event.type === 'modified') { const updatedFile = await fileHandle.getFile(); console.log('文件已更新,新大小:', updatedFile.size); console.log('新内容:', await updatedFile.text()); } }); // 若需要停止监听,可调用 watcher.cancel() }方案3:本地临时缓存(仅适用于非实时场景)
对于必须兼容旧浏览器且不需要实时跟踪的场景,可以在用户选择文件后将内容缓存到内存(比如Blob对象),当用户手动触发刷新时重新读取文件——但这种方式无法自动感知文件的外部修改。
测试代码
HTML
<!DOCTYPE html> <input type="file" id="file" /> <p id="info"></p>
CSS
#info { font-family: Courier; font-size: 0.9em; }
JavaScript
window.addEventListener('load', function() { window.setInterval(function() { var logFile = document.querySelector('#file').files[0]; if (logFile) { document.querySelector('#info').innerHTML = '<br/>' + (new Date()).toString() + '<br/>Last modified: ' + logFile.lastModified + '<br/>Size: ' + logFile.size; } }, 1000); });
内容的提问来源于stack exchange,提问作者user1854856

