【问题标题】:How to upload and read CSV files in React.js?如何在 React.js 中上传和读取 CSV 文件?
【发布时间】:2017-11-29 20:16:08
【问题描述】:

我希望用户上传一个 .csv 文件,然后让浏览器能够解析该文件中的数据。我正在使用 ReactJS。这将如何工作?谢谢。

【问题讨论】:

  • 你尝试了什么?
  • @Jonnysai 有许多使用 ReactJS 读取文件的包,但似乎没有一个包处理 CSV 文件。
  • 您能详细说明一下吗? “解析” .csv 可能意味着很多事情。 .csv 中的数据是否应该以某种方式格式化和显示?
  • @ZacCollier 解析不是问题,它以可读格式获取数据

标签: javascript reactjs csv user-input


【解决方案1】:

想通了。 react-file-reader 和 HTML5 的 FileReader 的组合(参见 this 页面)。

将 react-file-reader 位放置在渲染中:

<ReactFileReader handleFiles={this.handleFiles} fileTypes={'.csv'}>
    <button className='btn'>Upload</button>
</ReactFileReader>

然后是上面的。

handleFiles = files => {
    var reader = new FileReader();
    reader.onload = function(e) {
        // Use reader.result
        alert(reader.result)
    }
    reader.readAsText(files[0]);
}

【讨论】:

  • 我试过这样做,我得到这个错误:TypeError: reader.readAsText is not a function。有什么建议吗?
  • @39fredy 确保您在文件对象上使用 readAsText(在这种情况下,文件 [0] 是文件对象)。你有更多的代码吗?
  • 由于某种原因 FileReader 无法正常工作,经过一番搜索后我不得不使用 window.FileReader 并且成功了。
  • react-file-reader 已被弃用 (2018)
【解决方案2】:

我会使用 Papa Parse (https://www.npmjs.com/package/papaparse)。这是一个示例反应组件:

class FileReader extends React.Component {
  constructor() {
    super();
    this.state = {
      csvfile: undefined
    };
    this.updateData = this.updateData.bind(this);
  }

  handleChange = event => {
    this.setState({
      csvfile: event.target.files[0]
    });
  };

  importCSV = () => {
    const { csvfile } = this.state;
    Papa.parse(csvfile, {
      complete: this.updateData,
      header: true
    });
  };

  updateData(result) {
    var data = result.data;
    console.log(data);
  }

  render() {
    console.log(this.state.csvfile);
    return (
      <div className="App">
        <h2>Import CSV File!</h2>
        <input
          className="csv-input"
          type="file"
          ref={input => {
            this.filesInput = input;
          }}
          name="file"
          placeholder={null}
          onChange={this.handleChange}
        />
        <p />
        <button onClick={this.importCSV}> Upload now!</button>
      </div>
    );
  }
}

export default FileReader;

【讨论】:

  • 如何将上传的 .xlsx 文件转换为 csv 然后用 papaparse 解析?
  • @GaboRuiz XLSX.utils.sheet_to_csv 来自 sheet.js。
【解决方案3】:

在 React (React.js) 中上传和读取 csv 文件的最简单方法是 react-papaparse (Home | Demo | Docs | Github)。

看下面的简单例子:

import React, { Component } from 'react'
import { CSVReader } from 'react-papaparse'

const buttonRef = React.createRef()

export default class CSVReader1 extends Component {
  handleOpenDialog = (e) => {
    // Note that the ref is set async, so it might be null at some point
    if (buttonRef.current) {
      buttonRef.current.open(e)
    }
  }

  handleOnFileLoad = (data) => {
    console.log('---------------------------')
    console.log(data)
    console.log('---------------------------')
  }

  handleOnError = (err, file, inputElem, reason) => {
    console.log(err)
  }

  handleOnRemoveFile = (data) => {
    console.log('---------------------------')
    console.log(data)
    console.log('---------------------------')
  }

  handleRemoveFile = (e) => {
    // Note that the ref is set async, so it might be null at some point
    if (buttonRef.current) {
      buttonRef.current.removeFile(e)
    }
  }

  render() {
    return (
      <>
        <h5>Basic Upload</h5>
        <CSVReader
          ref={buttonRef}
          onFileLoad={this.handleOnFileLoad}
          onError={this.handleOnError}
          noClick
          noDrag
          onRemoveFile={this.handleOnRemoveFile}
        >
          {({ file }) => (
            <aside
              style={{
                display: 'flex',
                flexDirection: 'row',
                marginBottom: 10
              }}
            >
              <button
                type='button'
                onClick={this.handleOpenDialog}
                style={{
                  borderRadius: 0,
                  marginLeft: 0,
                  marginRight: 0,
                  width: '40%',
                  paddingLeft: 0,
                  paddingRight: 0
                }}
              >
                Browe file
              </button>
              <div
                style={{
                  borderWidth: 1,
                  borderStyle: 'solid',
                  borderColor: '#ccc',
                  height: 45,
                  lineHeight: 2.5,
                  marginTop: 5,
                  marginBottom: 5,
                  paddingLeft: 13,
                  paddingTop: 3,
                  width: '60%'
                }}
              >
                {file && file.name}
              </div>
              <button
                style={{
                  borderRadius: 0,
                  marginLeft: 0,
                  marginRight: 0,
                  paddingLeft: 20,
                  paddingRight: 20
                }}
                onClick={this.handleRemoveFile}
              >
                Remove
              </button>
            </aside>
          )}
        </CSVReader>
      </>
    )
  }
}

【讨论】:

    【解决方案4】:

    其他答案提到了使用 Papa Parse 进行基于浏览器的解析,我认为还值得一提的是使用基于后端的解析和预构建 React 组件的gluestick (https://github.com/hotgluexyz/gluestick)。

    如果您希望对输入数据或任何列映射进行验证,我建议您查看 React 组件和与之打包的 Python 后端 API。

    回购链接到 CodeSandbox (https://1c1dl.csb.app/) 上的演示

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-04
      • 2012-11-20
      • 2014-09-02
      • 2021-09-23
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      • 2019-05-05
      相关资源
      最近更新 更多