【问题标题】:Load local file into javascript variable from public website从公共网站将本地文件加载到 javascript 变量中
【发布时间】:2021-01-09 18:32:58
【问题描述】:

与类似的问题不同,这些问题涉及从本地打开的 .html 文件在浏览器中运行的 javascript,我正在寻找一种在 2020 年 9 月从公共网站访问时有效的解决方案,因为许多浏览器似乎已经加强了安全性并接受了答案不再有效。

我的用例是我希望用户通过输入表单选择一个文件,然后向他们提供修改文件内容的选项,然后再将其上传到服务器(此时可能使用 ajax)。

我意识到一种解决方法可能是将文件正常上传到服务器,读取服务器上的文件,将内容ajax 回给用户,让他们修改它,然后将其ajax 回服务器。如果可能的话,我想保存一次往返并在第一次将文件内容直接读取到 javascript 变量中。

从我发现的一个类似问题:

<input type="file" onchange="this.files[0].text().then(t => console.log(t))" />

如果我从我的计算机(即file://)打开 .html 网站,这可以工作,但如果我从公共域(https://)打开,则不行。

是否有另一种在最新(2020 年 9 月)Chrome / Firefox 中仍然有效的方法?

【问题讨论】:

  • 我认为你做不到。如果您检查输入项的值,您会看到类似c:\fakepath\filename.ext 的内容,因此您无论如何都无法在任何应用程序中打开该文件。

标签: javascript file file-upload upload


【解决方案1】:

这实际上是可能的。

我已经放弃了。我确信我必须将文件上传到服务器,然后通过 ajax 将其发送回客户端,然后使用 用户,然后将其发送回服务器。

纯 Javascript

并非如此。我找到了这个链接:https://web.dev/read-files/ 其中描述了以下方法:

<!-- Copyright 2018 Google LLC.
     SPDX-License-Identifier: Apache-2.0 -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Read an image file</title>
    <link rel="shortcut icon" 
          href="https://cdn.glitch.com/9b775a52-d700-4208-84e9-18578ee75266%2Ficon.jpeg?v=1585082912878">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/styles.css">
  </head>
  <body>
    <h1>
      Read an image file
    </h1>
    <input type="file" id="file-selector">
    <p id="status"></p>
    <div>
      <img id="output">
    </div>
    <script>
      const status = document.getElementById('status');
      const output = document.getElementById('output');
      if (window.FileList && window.File && window.FileReader) {
        document.getElementById('file-selector').addEventListener('change', event => {
          output.src = '';
          status.textContent = '';
          const file = event.target.files[0];
          if (!file.type) {
            status.textContent = 'Error: The File.type property does not appear to be supported on this browser.';
            return;
          }
          if (!file.type.match('image.*')) {
            status.textContent = 'Error: The selected file does not appear to be an image.'
            return;
          }
          const reader = new FileReader();
          reader.addEventListener('load', event => {
            output.src = event.target.result;
          });
          reader.readAsDataURL(file);
        }); 
      }
    </script>
  </body>
</html>

上面的代码将允许用户从他们的 HD 中选择一个图像,然后它使用 FileReader API 将数据加载到 javascript 中,而无需将其发送到服务器。我在其他地方读到过 FileReader 不能像这样通过网络工作,但我错了。

如果您想读取另一种文件,请确保在 FileReader 上调用不同的方法,例如 readAsText 用于文本,甚至作为数组缓冲区 readAsArrayBuffer

该链接有更多详细信息。

2020 年 10 月 2 日在 Windows 10 上测试

  • Firefox 81.0 64 位
  • Chrome 85.0.4183.121(官方版本)(64 位)
  • Edge 85.0.564.68(官方版本)(64 位)

反应

最简单的方法是使用 react-dropzonehttps://github.com/react-dropzone/react-dropzone 以下来自官方文档 (MIT):

import React, {useCallback} from 'react'
import {useDropzone} from 'react-dropzone'

function MyDropzone() {
  const onDrop = useCallback((acceptedFiles) => {
    acceptedFiles.forEach((file) => {
      const reader = new FileReader()

      reader.onabort = () => console.log('file reading was aborted')
      reader.onerror = () => console.log('file reading has failed')
      reader.onload = () => {
      // Do whatever you want with the file contents
        const binaryStr = reader.result
        console.log(binaryStr)
      }
      reader.readAsArrayBuffer(file)
    })
    
  }, [])
  const {getRootProps, getInputProps} = useDropzone({onDrop})

  return (
    <div {...getRootProps()}>
      <input {...getInputProps()} />
      <p>Drag 'n' drop some files here, or click to select files</p>
    </div>
  )
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-07
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    相关资源
    最近更新 更多