4

我正在开发一个简单的 React Web 应用程序,它可以在 IPFS 中添加和检索文件。

将文件添加到 IPFS 时,页面上会出现添加文件的名称(即医疗文件)以及“查看文件”按钮。

单击按钮时,应使用 react-pdf 中的“文档”组件查看文件[ https://www.npmjs.com/package/react-pdf | (Document file="..." 。文件可以是 URL、base64 内容、Uint8Array等。)

从 IPFS 添加和检索文件成功。从 IPFS 中检索到的Uint8Array形式的文件被传递给 Main.js 组件内的 Document 组件以查看 pdf 文件。但是,该页面未能加载 PDF 文件。另外,我得到一个错误:

Error: "Setting up fake worker failed: "window.pdfjsWorker is undefined"."

请注意,我在 Main.js 中有以下内容:

  <Document file={{ data: pdfFile.content }}></Document>

应用程序.js

      import React, { Component } from "react";
import Web3 from "web3";
import "./App.css";
import Meme from "../abis/Meme";
import Addressbar from "./Addressbar";
import Main from "./Main";

class App extends Component {
  async componentDidMount() {
    await this.getWeb3Provider();
    this.loadBlockchainData();
  }

  async getWeb3Provider() {
    if (window.ethereum) {
      window.web3 = new Web3(window.ethereum);
      await window.ethereum.enable();
    } else if (window.web3) {
      window.web3 = new Web3(window.web3.currentProvider);
    } else {
      window.alert(
        "Non-Ethereum browser detected. You should consider trying MetaMask!"
      );
    }
  }

  async loadBlockchainData() {
    const web3 = window.web3;
    // Load the account
    const accounts = await web3.eth.getAccounts();
    this.setState({ account: accounts[0] });
    /*Get an instance of the deployed smart contract in Javascript to allow us to 
     call the functions of the smart contract*/
    const networkId = await web3.eth.net.getId();
    const networkData = Meme.networks[networkId];
    if (networkData) {
      const contract = new web3.eth.Contract(Meme.abi, networkData.address);
      this.setState({ contract: contract });

      // Fetching the file hashes from the smart contract
      const count = await contract.methods.getfileHashesCount().call();
      for (var i = 0; i < count; i++) {
        const fileHash = await contract.methods.fileHashes(i).call();
        this.setState({
          fileHashes: [...this.state.fileHashes, fileHash]
        });
      }
    } else {
      window.alert("The contract is not found in your blockchain.");
    }
  }

  constructor(props) {
    super(props);
    // Setting the account (1)
    this.state = {
      account: null,
      fileHashes: [],
      contract: null,
      buffer: null
    };
  }

  // Setting the buffer
  setBuffer = data => {
    this.setState({ buffer: data });
    console.log("buffer data", this.state.buffer);
  };

  // Storing/adding the file hash on the blockchain
  storeFileHash = hash => {
    this.state.contract.methods
      .addFileHash(hash)
      .send({ from: this.state.account })
      .then(r => {
        return this.setState({ fileHashes: [...this.state.fileHashes, hash] });
      });

    //console.log("fileHashes", this.state.fileHashes);
  };

  render() {
    return (
      <div className="container">
        <div>
          <Addressbar account={this.state.account} />
        </div>

        <div>
          <Main
            fileHashes={this.state.fileHashes}
            setBuffer={this.setBuffer}
            buffer={this.state.buffer}
            storeFileHash={this.storeFileHash}
          />
        </div>
      </div>
    );
  }
}

export default App;

主要.js

    import React, { Component } from "react";
import { Document, Page } from "react-pdf";
//import { Document } from "react-pdf/dist/entry.webpack";
//import { pdfjs } from "react-pdf";
//pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;

//Required module(s)
const ipfsAPI = require("ipfs-api");

/*** Connceting to the ipfs network via infura gateway ***/
const ipfs = ipfsAPI("ipfs.infura.io", "5001", { protocol: "https" });

export class Main extends Component {
  /*
  state = {
    pdfFiles: []
  };
  */
  state = {
    pdfFiles: [],
    text: "Hi World"
  };

  captureFile = event => {
    event.preventDefault();
    // Fetch the file chosen
    const file = event.target.files[0];
    console.log("The original file : ", file);
    // Convert the file to a buffer
    const reader = new window.FileReader();
    reader.readAsArrayBuffer(file);
    reader.onloadend = () => {
      const arr = new Uint8Array(reader.result);
      console.log("Uint8Array ouptut", arr);
      console.log("reader.result output : ", reader.result);
      console.log("Buffer(reader.result) output : ", Buffer(reader.result));
      this.props.setBuffer(Buffer(reader.result));
    };
  };

  onSubmit = event => {
    event.preventDefault();
    console.log("Submitting file to IPFS......");
    console.log(this.props.buffer);

    // Adding the file to IPFS
    ipfs.files.add(this.props.buffer, (error, result) => {
      if (error) {
        console.log(error);
        return;
      }
      console.log("File added succesfully");
      console.log("IPFS result", result);

      // Storing the file hash on the blockchain
      this.props.storeFileHash(result[0].hash);
    });
  }; // end of sumbit event

  onClick = event => {
    event.preventDefault();
    console.log("Button clicked......");
    console.log(this.state.text);

    /*** Getting the uploaded file via hash code ***/
    const that = this; // NECESSARY
    ipfs.files.cat(event.target.name, function(err, file) {
      console.log("Getting files from IPFS ....... ");
      //console.log("File path ", file.path);
      //console.log("File hash", file.hash);
      console.log("The Unit8Array file content: ", file);
      const unit8Array_ = {
        content: file
      };
      console.log("Printing (1)......", unit8Array_.content);
      that.setState({ text: "Hi America" });
      console.log(that.state.text);
      that.setState({ pdfFiles: [...that.state.pdfFiles, unit8Array_] });
    });
  }; // end of sumbit event

  render() {
    return (
      <div className="container-fluid mt-5">
        <div className="row">
          <main>
            <div>
              <h3>Medical Files-Upload: </h3>
              <form onSubmit={this.onSubmit}>
                <div>
                  <label className="mr-2">Upload your medical document:</label>
                  <input type="file" onChange={this.captureFile} />
                  <input type="submit" />
                </div>
              </form>
            </div>

            <hr></hr>

            <div>
              <h5>PDF Document: {this.state.text} </h5>
              {this.state.pdfFiles.map((pdfFile, key) => {
                return (
                  <div>
                    <p>{console.log("Printing (2)....", pdfFile.content)}</p>
                    <Document file={{ data: pdfFile.content }}></Document>
                  </div>
                );
              })}
            </div>

            <hr></hr>
            <div>
              <h3>Medical Files-View: </h3>
              {this.props.fileHashes.map((fileHash, key) => {
                return (
                  <p>
                    {" "}
                    Medical File{" "}
                    <button name={fileHash} onClick={this.onClick}>
                      View File
                    </button>{" "}
                  </p>
                );
              })}
            </div>
          </main>
        </div>
      </div>
    );
  }
}

export default Main;

地址栏.js

import React, { Component } from "react";

class Addressbar extends Component {
  render() {
    return (
      <nav className="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
        <ul className="navbar-nav px-3">
          <li className="nav-item text-nowrap d-none d-sm-none d-sm-block">
            <small className="text-white">
              <span id="account">
                {"Your account address: " + this.props.account}
              </span>
            </small>
          </li>
        </ul>
      </nav>
    );
  }
}

export default Addressbar;
4

1 回答 1

4

如果您使用的是 create-react-app biolerplate:

将您的代码更改为:

import { Document, Page, pdfjs } from "react-pdf";
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;

它会起作用的。

感谢@frankenapps 提出了一个好的做法。

另请参阅此创建反应应用程序

于 2021-01-01T19:39:09.370 回答