我通过chrome扩展名将文件上传为表单数据,我的代码如下。这里的问题是文件浏览窗口仅打开一秒钟,然后消失。 该问题仅出现在Mac OS中。
manifest.json:
"background": { "scripts": ["jszip.js", "background.js"] },
background.js:
chrome.runtime.onMessage.addListener(function (msg) { if (msg.action === 'browse') { var myForm=document.createElement("FORM"); var myFile=document.createElement("INPUT"); myFile.type="file"; myFile.id="selectFile"; //myFile.onclick="openDialog()"; myForm.appendChild(myFile); var myButton=document.createElement("INPUT"); myButton.name="submit"; myButton.type="submit"; myButton.value="Submit"; myForm.appendChild(myButton); document.body.appendChild(myForm); } });
popup.js:
window.onload = function () { chrome.runtime.sendMessage({ action: 'browse' }); }
您想让用户从弹出窗口中选择并上传文件。但是在OSX中,一旦打开文件选择器对话框,弹出窗口便失去焦点并关闭,从而导致其JS上下文也被破坏。因此,对话框打开并立即关闭。
这是MAC上的一个 已知错误 ,已有一段时间了。
您可以将对话框打开逻辑移动到背景页面,而不受焦点丢失的影响。您可以从弹出窗口向后台页面发送一条消息,请求启动浏览和上传过程(请参见下面的示例代码)。
manifest.json
{ ... "background": { "persistent": false, "scripts": ["background.js"] }, "browser_action": { "default_title": "Test Extension", // "default_icon": { // "19": "img/icon19.png", // "38": "img/icon38.png" // }, "default_popup": "popup.html" }, "permissions": [ "https://www.example.com/uploads" // The above permission is needed for cross-domain XHR ] }
popup.html
... <script src="popup.js"></script> </head> <body> <input type="button" id="button" value="Browse and Upload" /> ...
popup.js
document.addEventListener('DOMContentLoaded', function () { document.getElementById('button').addEventListener('click', function () { chrome.runtime.sendMessage({ action: 'browseAndUpload' }); window.close(); }); });
background.js
var uploadUrl = 'https://www.example.com/uploads'; /* Creates an `input[type="file]` */ var fileChooser = document.createElement('input'); fileChooser.type = 'file'; fileChooser.addEventListener('change', function () { var file = fileChooser.files[0]; var formData = new FormData(); formData.append(file.name, file); var xhr = new XMLHttpRequest(); xhr.open('POST', uploadUrl, true); xhr.addEventListener('readystatechange', function (evt) { console.log('ReadyState: ' + xhr.readyState, 'Status: ' + xhr.status); }); xhr.send(formData); form.reset(); // <-- Resets the input so we do get a `change` event, // even if the user chooses the same file }); /* Wrap it in a form for resetting */ var form = document.createElement('form'); form.appendChild(fileChooser); /* Listen for messages from popup */ chrome.runtime.onMessage.addListener(function (msg) { if (msg.action === 'browseAndUpload') { fileChooser.click(); } });
注意 : 为了安全起见,fileChooser.click() 只有 在用户互动的情况下,Chrome才会执行。 在上面的示例中,用户单击弹出窗口中的按钮,该按钮将消息发送到调用的后台页面fileChooser.click();。如果您尝试以编程方式调用它,则将无法使用。(例如,在文档加载时调用它不会有任何效果。)
fileChooser.click()
fileChooser.click();