从公共网站将本地文件加载到javascript变量中

时间:2020-09-23 14:15:56

标签: javascript file file-upload upload

与类似的问题(与从本地打开的.html文件在浏览器中运行的javascript有关)不同,我正在寻找一种解决方案,该解决方案在许多浏览器似乎已加强安全性并被接受后于2020年9月从公共网站访问时可以正常工作答案不再起作用。

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

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

从类似的问题中我发现:

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

,并且如果我从计算机(即file://)打开.html网站,此方法有效,但是如果我从公共域(https://)打开.html网站,则无效。

还有另一种方法可以在最新(2020年9月)Chrome / Firefox中运行吗?

1 个答案:

答案 0 :(得分:0)

实际上这是可能的。

我已经放弃了。我确定我必须将文件上传到服务器,然后通过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>

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

如果您想读取其他类型的文件,请确保在FileReader上调用其他方法,例如为文本readAsText或作为数组缓冲区readAsArrayBuffer调用。

链接具有更多详细信息。

在Windows 10上于2020-10-02进行测试

  • 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>
  )
}
相关问题