HTML的IFrame不允许下载文件。

3

我想下载一个基于接收到的值自动构建的文件。这是我的代码:

<html>
<head>
<script>
    var myList=[];
    window.onmessage = function(event){
    if (event.data) {
      myList = event.data;
      if (myList.length>0) {
        buildHtmlTable();
      }
    }
    else {
      myList = [];
    }
  };
 function buildHtmlTable() {
     var columns = addAllColumnHeaders(myList);
 
     for (var i = 0 ; i < myList.length ; i++) {
         var row$ = $('<tr/>');
         for (var colIndex = 0 ; colIndex < columns.length ; colIndex++) {
             var cellValue = myList[i][columns[colIndex]];
 
             if (cellValue == null) { cellValue = ""; }
 
             row$.append($('<td/>').html(cellValue));
         }
         $("#excelDataTable").append(row$);
         
     }
     return exportF(); // Make Excel file download now
 }
 function addAllColumnHeaders(myList)
 {
     var columnSet = [];
     var headerTr$ = $('<tr/>');
 
     for (var i = 0 ; i < myList.length ; i++) {
         var rowHash =`enter code here` myList[i];
         for (var key in rowHash) {
             if ($.inArray(key, columnSet) == -1){
                 columnSet.push(key);
                 headerTr$.append($('<th/>').html(key));
             }
         }
     }
     $("#excelDataTable").append(headerTr$);
 
     return columnSet;
 }
 function exportF() {
  var table = document.getElementById("excelDataTable");
  var html = table.outerHTML;

  var url = 'data:application/vnd.ms-excel,' + escape(html);
  var link = document.getElementById("downloadLink");
  link.setAttribute("href", url);
  link.setAttribute("download", "export.xls"); // Choose the file name here
  link.click(); // Download your excel file   
  return false;
}
 </script>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body onLoad="">
    <table id="excelDataTable" border="1">
     </table>
     <a style="display: none" id="downloadLink"></a>
</body>

</html>

代码本身可以正常工作,但我收到的错误是“下载不允许。发起或实例化下载的框架被沙盒化,但标志'allow-downloads'未设置。有关更多详细信息,请参见https://www.chromestatus.com/feature/5706745674465280。”
我该怎么办才能解决这个问题?感觉我已经尝试了所有能找到的东西,但似乎没有任何东西能使它下载。

你能编辑父页面吗?如果可以,你尝试在<iframe ...>标签中添加sandbox="allow-downloads"了吗? - verjas
3个回答

7

正如警告消息所述,如果受保护的 iframe 没有 allow-downloads 权限,则无法从中初始化下载。

所有解决方案都意味着可以访问嵌入该 iframe 的页面(以下简称“宿主”)。

最简单和推荐的方法是

要求宿主在定义其 iframe 时添加此权限:

<iframe src="yourpage.html" sandbox="allow-scripts allow-downloads"></iframe>

另一种方式是要求他们完全不对该iframe进行沙盒处理,

<iframe src="yourpage.html"></iframe>

我猜测,如果他们没有这样做,那是因为他们不信任你的页面。


最后一种更复杂的方法是将生成的文件传回父窗口。

为此,您需要为客户定义新的 API。
您可以显然地向他们发出全局 message 事件,但我认为最干净的方法是让他们在 myList 数据旁边传递一个MessageChannel 的 MessagePort,这样他们可以在那里轻松等待响应,并确信他们只会捕获响应,而不是其他无关的消息。

因此,在嵌入器页面中,他们将执行以下操作:

frame.onload = (evt) => {
  const channel = new MessageChannel();
  // handle the response from the iframe
  channel.port2.onmessage = (evt) => {
    const file = evt.data;
    saveAs( file, "file.html" ); // the embedder is reponsible to initialize the download
  };
  frame.contentWindow.postMessage( embedders_data, [ channel.port1 ] );
};

在您的页面中,您需要这样做:

window.onmessage = (evt) => {
  const myList = evt.data;
  // get the MessageChannel's port out of the transfer-list
  const port = evt.ports[ 0 ];
  // buildHtmlTable has to return the final file, not to make it download
  const file = buildHtmlTable( myList );
  if( port ) { 
    port.postMessage( file ); // send back to embedder
  }
};

可以在实时plnkr中查看。

提示:请注意,您的文件不是xlsx文件,而是HTML标记。


0

正确答案

在正常情况下,Kaiido的回答确实是您问题的正确解决方案。然而,在您的情况下,它们不会起作用。

适用于Wix的解决方案

由于您正在使用Wix,因此您无法直接编辑iframe元素的Sandbox属性。这就是Wix的工作方式。但是,您可以使用自定义代码(仅适用于高级网站)获取iframe的类名,并编程使用JavaScript将新属性设置为现有的iframe。

您需要使用Web检查器找到类名(Wix中的iframes没有ID),然后将“allow-downloads”添加到sandbox属性中。您可能还需要使用js重新加载iframe。转到您网站的设置->自定义代码->在body标记末尾创建自定义代码。


如果您没有高级网站,则不幸的是无法执行此操作。这是由于Wix作为平台的限制。如果这对您的项目绝对必要,我建议您不要使用Wix,因为他们在处理非其制造的技术时会限制开发人员的自由。更不用说他们将自定义元素等功能锁定在付费墙后。因此,在承诺托管计划之前,我们甚至无法测试我们的想法。对于未来阅读此内容的任何人,请考虑这一点并了解其他平台。


-1

感谢回答,我没有在推荐的答案中找到解决方案。我做的是创建了一个全新的页面,而不是初始化一个HTML iframe,我将当前窗口重定向到我创建的新页面。新页面从“www.page.com/?page={value}”获取变量并从那里下载所需内容。虽然有点混乱,但它可以工作,所以如果其他人也遇到这个问题,我建议使用这种方法(如果您正在使用Wix)。


为什么“你没有在推荐的答案中找到解决方案”?是什么阻止了你应用其中一个三个解决方案?如果你需要更多信息/建议,你知道可以在回答中发表评论。此外,告诉我们你的具体情况会更好地帮助你(例如,为什么你的页面一开始就被加载到iframe中?谁在加载这个页面等)。 - Kaiido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接