从本地文件读取React.js

时间:2019-07-12 13:00:03

标签: node.js reactjs fs

我目前在我的应用程序中使用对node js的反应。

我正在尝试从文本文件读取内容,当我尝试其他操作时会遇到不同的错误。通过研究,从文件读取的最简单路径是使用“ fs”,因此我将发布尝试从本地文件(客户端)读取的两种方法。

如果有人可以帮助解决我的错误,甚至向我展示从本地文件中读取内容的另一种方式,我将不胜感激!

import React ...
import { readFile, readFileSync } from 'fs';
// other imports

class Background extends Component {
     // my constructor

     componentDidMount() {
         this.loadMe();
     }

     loadMe() {
          var file = './read_file';

          /* WAY 1: Asynchronously using readFile */
          readFile(file, function(err, data) {
               if (err) { console.log(err) }
               console.log(data);
          }

          /* WAY 2: Synchronously using readFileSync */
          var data = readFileSync(file);
          console.log(data);
     }
}

很明显,我不是同时运行两种方式。我基本上还从其他堆栈溢出答案和一些在线教程中复制了代码。我调查了FileReader,但无法正常工作。

我当前收到的错误:TypeError: Object(...) is not a function 指向var data = readFileSync(file);

谢谢!

3 个答案:

答案 0 :(得分:0)

fs是为Node.js之类的服务器JS env保留的库。

答案 1 :(得分:-1)

无法直接从浏览器打开和编辑文件。 可以,但是,可以打开文件,进行编辑,然后下载已编辑的文件。

您需要一个input类型的file元素,因为这样浏览器可以保证页面只能访问用户明确选择的文件。 (请告诉我评论中是否不清楚。如果不是,我会尽力解释。)

在下面的示例中,我将使用textarea元素来编辑文件的内容,但是一旦您将内容包含在字符串变量中,就可以用代码或随意更改它。

<!DOCTYPE html>
<html>
<head>
    <title>FileReader Example</title>
    <meta  charset="utf-8"/>
    <script>
        document.addEventListener('DOMContentLoaded',function() {
            var fileInput       = document.getElementById("fileInput");
            var textArea        = document.getElementById("fileEditor");
            var saveFileButton  = document.getElementById("saveFileButton");
            var downloadAnchor  = document.getElementById("downloadAnchor");

            function base64EncodeUnicode(str) {
                // First we escape the string using encodeURIComponent to get the UTF-8 encoding of the characters, 
                // then we convert the percent encodings into raw bytes, and finally feed it to btoa() function.
                utf8Bytes = encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
                        return String.fromCharCode('0x' + p1);
                });

                return btoa(utf8Bytes);
            }

            function handleInputFileChange(event) {
                //if we didnd't already have the "fileInput" var in scope, we could use "event.target" to get it
                if(fileInput.files.length>=1) {
                    //In this example, I'm putting the selected file's name in the title. You don't need to do this
                    document.title = fileInput.files[0].name;
                    downloadAnchor.setAttribute("download","edited_"+fileInput.files[0].name);
                }
                else {
                    document.title = "FileReader Example";
                    downloadAnchor.setAttribute("download","edited_file.txt");
                }
                var fr = new FileReader();
                fr.readAsText(fileInput.files[0]);
                fr.onload = function (event) {
                    //Both "event.target.result" and "fr.result" contain the file's contents (because "event.target" is === "fr")

                    textArea.value = event.target.result;
                    // OR
                    //textArea.value = fr.result;
                }
            }
            //The next is the fucntion returns a special kind of URL, a Data URL.
            //These kind of URLs don't point to a file, they ARE the data.
            //Read more here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
            function getDownloadableTextAreaContents() {
                return "data:text/plain,"+encodeURIComponent(textArea.value);
            }
            function onDownloadClick(event) {
                //https://stackoverflow.com/a/247261/6302540
                //var urlObject = "data:text/plain;base64,"+btoa(unescape(encodeURIComponent(textArea.value)));
                var urlObject = getDownloadableTextAreaContents();
                downloadAnchor.setAttribute("href",urlObject);
                downloadAnchor.click();
            }

            fileInput.addEventListener("change",handleInputFileChange);
            saveFileButton.addEventListener("click",onDownloadClick);
        },false);
    </script>
</head>
<body>
    <h1>File Reader Example:</h1>
    <input id="fileInput" type="file" accept=".txt"/>
    <textarea name="File Editor" id="fileEditor" placeholder="Your file's contents will show up here once you select the file!"></textarea>
    <button id="saveFileButton">Save File</button>
    <!--The next <a> tag is just a trick to make the browser download a file. It isn't displayed (style="display: none;")-->
    <a id="downloadAnchor" download="edited_file.txt" href="data:text/plain," style="display: none;"></a>
</body>
</html>

这是普通JS中的示例,但是您可以轻松地对此做出反应。其中一些改编是:

  • 删除id,因为您在React中不需要它们;
  • 您将拥有一个controlled textarea component,而不是简单的textarea。使用受控组件,可以轻松设置和获取文本区域的值。 (如果您不了解React的状态和道具或受控组件的工作方式,则可以使用引用(这使得React代码几乎与普通JS相同),但我不建议您这样做,因为它是反模式并且应该只在极少数情况下使用,例如非常精美的动画);
  • 使用changeclick道具可以轻松转换onChangeonClick事件;
  • 要执行downloadAnchor.click(),您可以关注this answer
  • 隐藏的锚点(<a>)的hrefdownload属性也可以是具有状态值的普通道具,例如:

在React中:

<a download={this.state.downloadFilename} href={this.state.dataURL} style="display: none;"/>

答案 2 :(得分:-1)

您可以使用https://github.com/kentcdodds/babel-plugin-preval之类的东西在前端react应用中使用fs模块。

使用以下命令安装preval.macro

npm i preval.macro --save

然后将其添加到您的应用程序

import preval from 'preval.macro';
const components = preval
    ` const fs = require('fs');
  const files = fs.readdirSync('src/atoms');
  module.exports = files;
`

组件将返回src / atoms下的文件夹。