0

我想知道如何为 HTML5“文件”对象定义文件引用,用作 JavaScript 函数的输入,该函数将文件转换为 Base64 编码,而不使用交互式文件输入元素。我看过 HTML5Rocks 示例和许多其他示例,但它们都使用一个<input type=file>元素来读取和收集有关要操作的文件的输入。我打算将图像文件(即二进制)作为输入,并输出 Base64 字符串。(也许这很明显,但我是 HTML5 和 JavaScript 世界的新手)

我的一些阅读似乎表明出于安全原因这是不可能的:JS 将能够运行任意文件。我想仔细检查一下。

“文件”输入类型的输出是什么?我可以以某种方式手动模仿它吗?(我在这里找到了一个关于直接将文件本身包含在 JS 中的参考资料,但是你能用二进制文件做到这一点吗?坦率地说,我也不确定我会如何在 FileMaker 方面做到这一点。我的计划,直到此时,是将文件从 FileMaker 导出到已知位置,然后将该位置用作 JavaScript 的输入)

整体情况:我正在尝试在 FileMaker 12 中创建一个自包含的 Web 查看器元素。在 FileMaker 中,我可以在运行之前动态定义我的 HTML 和 JavaScript。我想动态地将 JavaScript 硬编码为已经包含基于数据库信息(即路径和文件名)的文件引用。这一切都在本地机器上运行,不涉及服务器。

我试图最小化最终用户为使文件编码而必须进行的交互:我不希望他们必须将图像放入数据库,然后还必须再次删除(或文件选择器)图像在网络查看器中。我想将所有这些代码保留在 FileMaker 数据库中,以使其更加便携和强大,即不必依赖互联网连接。因此,用户将他们的文件放入数据库,数据库会自动检测该事件,计算 JavaScript(包括文件的路径),然后 JavaScript 在其上运行 Base64 函数,将编码字符串返回到数据库。

也许我应该反过来做:让用户将文件放入 JavaScript 区域,然后将其复制到数据库中。不过,不确定 JavaScript 是否有任何与数据库交互的句柄。

------------------------ 编辑(除了原始问题的一些标记和标记)

让我们暂时忽略 FileMaker 的整个方面。我决定走只使用 HTML5 和 JavaScript 作为文件输入部分的路线(而不是尝试在 FM 中读取它然后输出到 JS)。只是想看看我是否可以让 JavaScript 部分工作。

这是我现在正在玩的一些代码。它主要来自 HTML5 Rocks 演示,以及我找到的 base64 编码例程。但是,我遇到了关于如何定义和调用我的阅读器、onload 事件和编码函数的问题。任何建议,将不胜感激:

    <script>
    //  From:  http://www.html5rocks.com/en/tutorials/file/dndfiles/
    //  JC update:  changing the handleFileSelect() function to do the base64 Processing

  function base64Encode(aFile) {
      /*
       * base64.js - Base64 encoding and decoding functions
       * See: http://developer.mozilla.org/en/docs/DOM:window.btoa
       *      http://developer.mozilla.org/en/docs/DOM:window.atob
       * Copyright (c) 2007, David Lindquist <david.lindquist@gmail.com>
       * Released under the MIT license
       *
       * JC, update:  Removed the 'atob' section of code; only need ENcoding, not DEcoding.
       */

      if (typeof btoa == 'undefined') {
          function btoa(str) {
              var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
              var encoded = [];
              var c = 0;
              while (c < str.length) {
                  var b0 = str.charCodeAt(c++);
                  var b1 = str.charCodeAt(c++);
                  var b2 = str.charCodeAt(c++);
                  var buf = (b0 << 16) + ((b1 || 0) << 8) + (b2 || 0);
                  var i0 = (buf & (63 << 18)) >> 18;
                  var i1 = (buf & (63 << 12)) >> 12;
                  var i2 = isNaN(b1) ? 64 : (buf & (63 << 6)) >> 6;
                  var i3 = isNaN(b2) ? 64 : (buf & 63);
                  encoded[encoded.length] = chars.charAt(i0);
                  encoded[encoded.length] = chars.charAt(i1);
                  encoded[encoded.length] = chars.charAt(i2);
                  encoded[encoded.length] = chars.charAt(i3);
              }
              return encoded.join('');
          }
      }
  }

  function handleFileSelect(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    var files = evt.dataTransfer.files; // FileList object - a FileList of File objects.
    var fReader = new FileReader () ;  
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
      if ( !f.type.match('image.*')) { continue; }    //To skip non-image files
      fReader.onLoad = (function (aFile) { return base64Encode(aFile); } ) (f);
      output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
                  f.size, ' bytes, last modified: ',
                  f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
                  '<br><br>' , fReader.readAsBinaryString(f) , '<br><br>', '</li>');
     //This defines the 'onLoad' behavior/function...I think.

    }
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
  }

  function handleDragOver(evt) {
    evt.stopPropagation();
    evt.preventDefault();
    evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
  }

  // Setup the dnd listeners.  [Slightly modified by JC]
  var dropZone = document.getElementById('drop_zone');
  dropZone.addEventListener('dragover', handleDragOver, false);
  dropZone.addEventListener('drop', handleFileSelect, false);
</script>
4

1 回答 1

0

不,在网络浏览器中,您不能访问用户计算机上的任意文件。永远不能。

您可以从网络获取文件(但仅当它们来自同一来源或通过 CORS 允许,并且file://协议不允许时才读取内容)、IndexedDB 数据库和 Chrome 的沙盒文件系统(它不是用户的文件系统 - 它只包含文件你自己放在那里)。

您可以自己创建“文件”:

var file = new Blob(["file content"], {type:"text/plain"})

Blob是的基类,File它通常可以在任何地方使用input.files[]

您可能有权从其他基于 JS 的环境(如小部件或浏览器扩展)访问本地文件。

于 2013-02-26T17:23:09.620 回答