上传到 IPFS 的 PDF 文件不显示

问题描述

背景

localhost 上运行我的应用程序时,我可以选择我的 PDF 文件并提交。我能够获取 IPFS 文件的路径并在控制台中显示该路径。

问题

添加此行以显示我的文件时,它不起作用并显示“未指定 PDF 文件”。

<Document src={https://ipfs.infura.io/ipfs/${this.state.ipfshash}} />

<Document file={https://ipfs.infura.io/ipfs/${this.state.docupayHash}} />

Web page result

我的尝试

我已经转到谷歌浏览器 (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 上查看了其他解决方案,但我发现没有一个与我的问题特别相关。感谢您的帮助和时间!

解决方法

尝试两件事:

  1. 添加 ?filename= 参数作为网关和 react-pdf 的提示:

    <Document src={`https://ipfs.infura.io/ipfs/${this.state.ipfshash}?filename=test.pdf`} />
    

    这将使网关返回的内容类型更加可靠并消除 react-pdf 中的假阴性。

  2. 运行您自己的网关,或联系 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 负载。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...