问题描述
背景
在 localhost
上运行我的应用程序时,我可以选择我的 PDF 文件并提交。我能够获取 IPFS 文件的路径并在控制台中显示该路径。
问题
添加此行以显示我的文件时,它不起作用并显示“未指定 PDF 文件”。
<Document src={
https://ipfs.infura.io/ipfs/${this.state.ipfshash}} />
<Document file={
https://ipfs.infura.io/ipfs/${this.state.docupayHash}} />
我的尝试
我已经转到谷歌浏览器 (ipfs.infura.io/ipfs/"QmUqB9dWDCeZ5nth9YKRJTQ6PcnfrGppx1vzdyNWV6rh8s"
) 中的链接,我可以在那里看到文件,所以我知道链接是正确的。
App.js
import React,{ Component } from "react";
import { Document,Page } from 'react-pdf';
import web3 from "./web3";
import ipfs from "./ipfs";
import storehash from "./storehash";
import "./styles/App.css";
class App extends Component {
state = {
contractHash: null,buffer: "",ethAddress: "",blockNumber: "",transactionHash: ""
};
captureFile = (event) => {
event.stopPropagation()
event.preventDefault();
const file = event.target.files[0];
let reader = new window.FileReader();
reader.readAsArrayBuffer(file);
reader.onloadend = () => this.convertToBuffer(reader);
};
convertToBuffer = async (reader) => {
// Convert file to buffer so that it can be uploaded to IPFS
const buffer = await Buffer.from(reader.result);
this.setState({buffer});
};
onClick = async () => {
try {
await web3.eth.getTransactionReceipt(this.state.transactionHash,(err,txReceipt) => {
console.log(err,txReceipt);
this.setState({txReceipt});
});
} catch (error) {
console.log(error);
}
}
onSubmit = async (event) => {
event.preventDefault();
// Take the user's MetaMask address
const accounts = await web3.eth.getAccounts();
console.log("Sending from Metamask account: " + accounts[0]);
// Retrieve the contract address from storehash.js
const ethAddress= await storehash.options.address;
this.setState({ethAddress});
// Save document to IPFS,return its hash,and set it to state
await ipfs.add(this.state.buffer,contractHash) => {
console.log(err,contractHash);
this.setState({ contractHash: contractHash[0].hash });
storehash.methods.setHash(this.state.contractHash).send({ from: accounts[0] },(error,transactionHash) => {
console.log(transactionHash);
this.setState({transactionHash});
});
})
};
render() {
return (
<div className="app">
<h3> Choose file to send to IPFS </h3>
<form onSubmit={this.onSubmit}>
<input type="file" onChange={this.captureFile} />
<button type="submit">Submit</button>
</form>
<Document file={`https://ipfs.infura.io/ipfs/${this.state.contractHash}`} />
<a href={`https://ipfs.infura.io/ipfs/${this.state.contractHash}`}>Click to download the file</a>
<button onClick = {this.onClick}>Get Transaction Receipt</button>
<p>IPFS Hash: {this.state.contractHash}</p>
<p>Contract Address: {this.state.ethAddress}</p>
<p>Tx Hash: {this.state.transactionHash}</p>
</div>
);
}
}
export default App;
MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16 <0.7.0;
contract MyContract {
string contractHash;
function setHash(string memory ipfsHash) public {
contractHash = ipfsHash;
}
function getHash() public view returns (string memory ipfsHash) {
return contractHash;
}
}
我在 SO 上查看了其他解决方案,但我发现没有一个与我的问题特别相关。感谢您的帮助和时间!
解决方法
尝试两件事:
-
添加
?filename=
参数作为网关和react-pdf
的提示:<Document src={`https://ipfs.infura.io/ipfs/${this.state.ipfshash}?filename=test.pdf`} />
这将使网关返回的内容类型更加可靠并消除
react-pdf
中的假阴性。 -
运行您自己的网关,或联系 Infura 并讨论提高您应用的请求限制。
仅供参考,我已经多次运行以下测试:$ curl -Ls 'https://dweb.link/ipfs/QmUqB9dWDCeZ5nth9YKRJTQ6PcnfrGPPx1vzdyNWV6rh8s?filename=test.pdf' > output && file output output: PDF document,version 1.5
几次后他们停止返回 PDF,而是返回带有
429 Too Many Requests
错误的 HTML 页面:output: HTML document,ASCII text,with CRLF line terminators $ cat output <html> <head><title>429 Too Many Requests</title></head> <body> <center><h1>429 Too Many Requests</h1></center> <hr><center>openresty</center> </body> </html>
react-pdf
很可能无法呈现您的 PDF,因为它收到的是429 Too Many Requests
错误响应而不是 PDF 负载。