javascript - HTML客户端可移植文件生成-无需外部资源或服务器调用

标签 javascript html uri client-side file-generation

我有以下情况:

我已经在公司内部服务器上设置了一系列Cron作业,以运行各种旨在检查数据完整性的PHP脚本。每个PHP脚本查询一个公司数据库,将返回的查询数据格式化为包含一个或多个<tables>的HTML文件,然后将该HTML文件作为附件邮寄到几封客户电子邮件中。根据我的经验,大多数PHP脚本只生成带有几个表的HTML文件,但是也有一些PHP脚本创建带有约30个表的HTML文件。选择HTML文件作为这些扫描的分发格式,因为HTML使在浏览器窗口中一次查看多个表变得容易。

我想为客户端添加功能,以将HTML文件中的表格下载为CSV文件。我希望客户端在怀疑基于表数据的数据完整性问题时会使用此功能。对于他们来说,理想的是能够拿到问题的表格,将数据导出到CSV文件,然后进一步研究。

由于需要将数据导出为CSV格式是由客户决定的,因此无法确定哪个表将受到审查,并且断断续续地使用我不想为每个表创建CSV文件。

通常,使用JavaScript / jQuery进行DOM遍历并使用服务器调用或Flash库将CSV文件数据生成为字符串以简化下载过程,创建一个CSV文件并不难。但我有一个限制条件:HTML文件必须是“便携式”的。

我希望客户能够获取他们的HTML文件,并对公司内部网外部的数据进行瓶坯分析。同样,这些HTML文件也可能会被存档,因此出于上述两个原因,在HTML文件中使导出功能“自包含”是非常理想的功能。

从HTML文件生成CSV文件的“便携式”约束意味着:

  • 我无法进行服务器调用。这意味着 ALL 文件生成必须在客户端完成。
  • 我希望电子邮件附带的单个HTML文件包含生成CSV文件的所有资源。这意味着我不能使用jQuery或Flash库来生成文件。

  • 我知道,出于明显的安全原因,任何浏览器均不支持使用JavaScript将文件写出到磁盘。我不想在没有用户知识的情况下创建文件;我想使用内存中的JavaScript生成文件,然后提示用户从内存中“下载”文件。

    我已经研究过将CSV文件生成为URI,但是根据我的研究和测试,这种方法存在一些问题:
  • IE(See Here)不支持文件的URI
  • FireFox中的
  • URIs使用随机文件名将文件保存为.part文件。

  • 令我痛苦的是,我可以接受IE <= v9不会为文件创建URI的事实。我想创建一个半跨浏览器的解决方案,其中Chrome,Firefox和Safari创建一个URI,以在JavaScript DOM遍历编译数据后下载CSV文件。

    我的示例表:
    <table>
        <thead class="resulttitle">
            <tr>
                <th style="text-align:center;" colspan="3">
                NameOfTheTable</th>
            </tr>
        </thead>
        <tbody>
            <tr class="resultheader">
                <td>VEN_PK</td>
                <td>VEN_CompanyName</td>
                <td>VEN_Order</td>
            </tr>
            <tr>
                <td class='resultfield'>1</td>
                <td class='resultfield'>Brander Ranch</td>
                <td class='resultfield'>Beef</td>
            </tr>
            <tr>
                <td class='resultfield'>2</td>
                <td class='resultfield'>Super Tree Produce</td>
                <td class='resultfield'>Apples</td>
            </tr>
            <tr>
                <td class='resultfield'>3</td>
                <td class='resultfield'>John's Distilery</td>
                <td class='resultfield'>Beer</td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
              <td colspan="3" style="text-align:right;">
              <button onclick="doSomething(this);">Export to CSV File</button></td>
            </tr>
        </tfoot>
    </table>
    

    我的示例JavaScript:
    <script type="text/javascript">
      function doSomething(inButton) {
    
        /* locate elements */
        var table = inButton.parentNode.parentNode.parentNode.parentNode;
        var name  = table.rows[0].cells[0].textContent;
        var tbody = table.tBodies[0];
    
        /* create CSV String through DOM traversal */
        var rows  = tbody.rows;
        var csvStr = "";
        for (var i=0; i < rows.length; i++) {
          for (var j=0; j < rows[i].cells.length; j++) {
            csvStr += rows[i].cells[j].textContent +",";
          }
          csvStr += "\n";
        }
    
        /* temporary proof DOM traversal was successful */
        alert("Table Name:\t" + name + "\nCSV String:\n" + csvStr);
    
        /* Create URI Here!
         * (code I am missing)
         */
    
        /* Approach #1 : Auto-Download From Browser
         * Attempts to redirect the browser to the URI
         * and have the browser download the data as a file
         *
         * Approach does downloads CSV data but:
         * In FireFox downloads as randomCharacers.part instead of name.csv
         * In Chrome downloads without prompting the user and without correct file name
         * In Safari opens the files in browser (textfile)
         */
        /* Approach #1 Code:
           var hrefData = "data:text/csv;charset=US-ASCII," + encodeURIComponent(csvStr);
           document.location.href = hrefData;
         */
    
        /* Approach #2 : Right-Click Save As Link...
         * Attempts to remove "Download Button"
         * and replace the it with an anchor tag <a>
         * that the user can use to download the data
         *
         * Approach sort of works better:
         * When clicking on the link:
         * In FireFox downloads as randomCharacers.part instead of name.csv
         * In Chrome downloads without prompting the user (uses correct name) 
         * In Safari opens the files in browser (textfile)
         * 
         * When right-click "Save As" on the link:
         * In FireFox prompts the user with filename: randomCharacers.part 
         * In Chrome  prompts the user with filename: "download"
         * In Safari  prompts the user with filename: "Unknown"
         */
        /* Approach #2 Code:
           var hrefData = "data:text/csv;charset=US-ASCII," + encodeURIComponent(csvStr);
           var fileLink = document.createElement("a");
           fileLink.href = hrefData;
           fileLink.type  = "text/csv";
           fileLink.innerHTML = "CSV Download Link";
           fileLink.setAttribute("download",name+".csv"); // for Chrome
           parentTD = inButton.parentNode;
           parentTD.appendChild(fileLink);
           parentTD.removeChild(inButton);
         */
      }
    </script>
    

    我正在寻找一个示例解决方案,其中上述示例表可以下载为CSV文件:

    使用URI 的

  • 使用<button><a>
  • 代码的工作方式如FireFox,Safari和Chrome的现代版本中所述
  • (1. 2.):
  • 提示用户保存文件
  • 用户不需要“右键单击另存为”
  • 自动将文件保存到默认浏览器保存目录
  • 默认文件名是带有.csv文件扩展名
  • 的表的名称

    我使用DOM遍历函数<script>添加了doSomething()标记。我需要的真正帮助是将URI格式化为doSomething()函数中所需的格式。方法2(请参阅我的代码)似乎最有前途。

    我愿意接受,如果陈述带有证据,则仅使用HTML和JavaScript是无法实现我想要的功能的;例如浏览器文档,DOM标准,JavaScript / ECMAscript文档或证明不可能的逻辑示例。

    话虽这么说,但我认为即使有一点技巧,也可以从具有更深背景/对URI有更多经验的人那里找到解决方案。

    最佳答案

    只要您不介意仅在IE10 +上支持IE10 +,请使用FileSaver.js。您可以生成CSV并将其附加到Blob,然后用saveAs() Blob。您将只能在支持<a download>的浏览器(例如Chrome)中保存已保存文件的文件名。

    关于javascript - HTML客户端可移植文件生成-无需外部资源或服务器调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11730487/

    相关文章:

    javascript - 检测 WordPress 中的浏览器下载错误

    php - 使用 JavaScript .match() 获取 YouTube ID

    javascript - JQuery 或 Javascript 在带有文本数组的 DIV 中旋转文本

    javascript - javascript 中的 pdf417 条码阅读器/解码器?

    html - 没有css3的html5中的旋转

    python unicode 正则表达式

    javascript - 构造函数中的构造函数 - 不好的做法?

    html - 可滚动区域的中心元素

    java - 如何从 FileProvider URI 获取真实路径?

    c# - 我怎样才能得到网站的baseurl?