我正在开发一个简单的 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;