IPFS入门实践

 

目录

IPFS安装:

Some things to try (Quick start)

Taking your Node Online

Transfer a file to IPFS

IPFS与DApp开发实战

7.1 安装Truffle unbox react

7.2 安装ipfs-api

7.3 修改智能合约代码

7.4 编译智能合约

7.5 部署智能合约

7.5 修改App.js文件

7.6 新建终端,执行"npm start"命令,

参考

IPFS安装:

$ tar xvfz go-ipfs.tar.gz

$ cd go-ipfs

$ ./install.sh

$ ipfs help

$ ipfs init

$ ipfs cat /ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/readme  

$ ipfs cat /ipfs//quick-start

 

Some things to try (Quick start)

Basic proof of 'ipfs working' locally:

echo "hello world" > hello
ipfs add hello
# This should output a hash string that looks something like:
# QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o
ipfs cat 

Add a file to ipfs:
$echo "hello world" >hello
$ipfs add hello


View it:
$ipfs cat 


Try a directory:
$ mkdir foo
$  mkdir foo/bar
$  echo "baz" > foo/baz
$  echo "baz" > foo/bar/baz
$  ipfs add -r foo


View things:
  ipfs ls 
  ipfs ls /bar
  ipfs cat /baz
  ipfs cat /bar/baz
  ipfs cat /bar
  ipfs ls /baz

Get:

  ipfs get  -o foo2
  diff foo foo2


Objects:

  ipfs object get 
  ipfs object get /foo2
  ipfs object --help


Pin + GC:

  ipfs pin add 
  ipfs repo gc
  ipfs ls 
  ipfs pin rm 
  ipfs repo gc


Daemon:

  ipfs daemon  (in another terminal)
  ipfs id


Network:

  (must be online)
  ipfs swarm peers  // ipfs swarm peers| wc -l
  ipfs id
  ipfs cat 


Mount:

  (warning: fuse is finicky!)
  ipfs mount
  cd /ipfs/
  ls


Tool:

  ipfs version
  ipfs update
  ipfs commands
  ipfs config --help
  open http://localhost:5001/webui


Browse:

  webui:

    http://localhost:5001/webui

 

Taking your Node Online

Once you’re ready to join your node to the public network, run the ipfs daemon in another terminal and wait for all three lines below to appear to know that your node is ready:

> ipfs daemon
Initializing daemon...
API server listening on /ip4/127.0.0.1/tcp/5001
Gateway server listening on /ip4/127.0.0.1/tcp/8080

Make note of the tcp ports you receive. If they are different, use yours in the commands below.

 

Transfer a file to IPFS

# On A
> ipfs add myfile.txt
added QmZJ1xT1T9KYkHhgRhbv8D7mYrbemaXwYUkg7CeHdrk1Ye myfile.txt

# On B
> ipfs get QmZJ1xT1T9KYkHhgRhbv8D7mYrbemaXwYUkg7CeHdrk1Ye
Saving file(s) to QmZJ1xT1T9KYkHhgRhbv8D7mYrbemaXwYUkg7CeHdrk1Ye
 13 B / 13 B [=====================================================] 100.00% 1s

>ipfs ls -v QmZJ1xT1T9KYkHhgRhbv8D7mYrbemaXwYUkg7CeHdrk1Ye

>ipfs block stat: 查询block的数据大小,不包含子块。
>ipfs refs -r:列出所有数据块的子块信息
>ipfs ls or ipfs object links:显示所有的子块和块的大小

实验效果图:

 IPFS入门实践_第1张图片

 ipfs cat /ipfs/QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg >cat.jpg 

 

QmRVWUfHFkEX8HGwtwau9pvcJ99vWySnQ9TryTQ6gqyJdB

 

  • IPFS与以太坊DApp结合的好处

    在以太坊平台上,往区块链写入数据需要花费以太币,调用智能合约执行每一行代码的时候,都需要一定量的gas交易费。区块链存储大数据成本很高,而且不合理。
    可以先将文件存储到IPFS,然后得到文件的Hash存储到以太坊区块链中。读取文件的时候,从以太坊区块链中获取文件的Hash,再通过Hash来读取IPFS网络上的文件。
    使用官方提供的ipfs-api,可以很方便地在代码中操作节点将数据上传到IPFS,或者通过Hash从IPFS读取数据。
    Truffle框架提供了快速搭建包含以太坊智能合约的React项目,可以通过"truffle unbox react"创建工程,然后安装ipfs-api依赖库。于是,可以在前端方便地调用IPFS的接口来读取、上传文件。

    truffle unbox react官网:
    http://truffleframework.com/boxes/react

IPFS与DApp开发实战

7.1 安装Truffle unbox react

新建一个空目录"ipfs_dapp",然后执行安装命令

truffle unbox react
wenzildeiMac:ipfs_dapp wenzil$ pwd
/Users/wenzil/Desktop/study/ipfs_dapp
wenzildeiMac:ipfs_dapp wenzil$ truffle unbox react
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!
  
Commands:
  
  Compile:              truffle compile
  Migrate:              truffle migrate
  Test contracts:       truffle test
  Test dapp:            npm test
  Run dev server:       npm run start
  Build for production: npm run build

7.2 安装ipfs-api

在打开ipfs daemon联网之后,输入以下指令
$cd client   su
#npm install --save ipfs-api 或者  npm install --save ipfs-http-client

 IPFS入门实践_第2张图片

7.3 修改智能合约代码

修改contracts目录中的"SimpleStorage.sol",修改后完整代码:

pragma solidity ^0.4.18;

contract SimpleStorage {
  // 用于存储图片的哈希值
  string storedData;

  function set(string x) public {
    storedData = x;
  }

  function get() public view returns (string) {
    return storedData;
  }
}    

 

7.5 编译部署智能合约

ipfs-dapp$truffle compile
ipfs-dapp$ truffle migrate --reset
记住address

进入remix-ide,复制SimpleStorage.sol代码,然后切换到"Run"菜单,选择"Injected Web3"进行智能合约的部署

IPFS入门实践_第3张图片

Remix-IDE部署智能合约

IPFS入门实践_第4张图片

Remix-IDE部署智能合约-确认

然后复制智能合约地址,App.js文件中会用到合约地址为:"0xb177d6cf6916f128c9931e610c63208d9c5a40f3"

7.5 修改App.js文件

import React, {Component} from 'react'
import SimpleStorageContract from 
'../build/contracts/SimpleStorage.json'
import getWeb3 from './utils/getWeb3'

import './css/oswald.css'
import './css/open-sans.css'
import './css/pure-min.css'
import './App.css'

const ipfsAPI = require('ipfs-api');
const ipfs = ipfsAPI({
  host: 'localhost',
  port: '5001',
  protocol: 'http'
});

const contract = require('truffle-contract')
const simpleStorage = contract(SimpleStorageContract)
let account;

// Declaring this for later so we can chain functions on SimpleStorage.
let contractInstance;

let saveImageToIPFS = (reader) => {
    return new Promise(function(resolve, reject) {
        const buffer = Buffer.from(reader.result);
        ipfs.add(buffer).then((response) => {
        console.log(response)
        resolve(response[0].hash);
     }).catch((err) => {
        console.error(err)
        reject(err);
     })
  })
}

class App extends Component {
   constructor(props) {
   super(props)

   this.state = {
       blockChainHash: null,
       web3: null,
       address: null,
       imageHash: null,
       isSuccess: false
  }
}

componentWillMount() {
    ipfs.swarm.peers(function(err, res) {
    if (err) {
      console.error(err);
    } else {
      // var numPeers = res.Peers === null ? 0 :     res.Peers.length;
      // console.log("IPFS - connected to " + numPeers + " peers");
      console.log(res);
    }
});

getWeb3.then(results => {
    this.setState({web3: results.web3})

    // Instantiate contract once web3 provided.
    this.instantiateContract()
  }).catch(() => {
    console.log('Error finding web3.')
  })
}

instantiateContract = () => {
  simpleStorage.setProvider(this.state.web3.currentProvider);
  this.state.web3.eth.getAccounts((error, accounts) => {
  account = accounts[0];
    simpleStorage.at('0xb177d6cf6916f128c9931e610c63208d9c5a40f3').then((contract) => {
    console.log(contract.address);
    contractInstance = contract;
    this.setState({address: contractInstance.address});
    return;
  });
})

}
render() {
  return (
    
智能合约地址:
{this.state.address}
上传图片到IPFS:
图片哈希值:{this.state.imageHash}
{ this.state.isSuccess ?
图片哈希成功写入区块链!
:
} { this.state.blockChainHash ?
从区块链读取到的哈希值:{this.state.blockChainHash}
:
} { this.state.blockChainHash ?
访问本地文件:
{"http://localhost:8082/ipfs/" + this.state.imageHash}
访问IPFS网关:
{"https://ipfs.io/ipfs/" + this.state.imageHash}
: }
); } } export default App

7.6 新建终端,执行"client$ npm run start"命令,

 

用react github 原始项目example跑的结果,看到这个图实属不易啊

小激动

IPFS入门实践_第5张图片

 

但是我们看到stored value:0是错误的,这是因为部署合约的网络是localhost:8545; 而项目运行时injected web3来自MetaMask;

所以需要MetaMask连接到localhost:8545.

点击右上角猫猫,new network->url: http://127.0.0.1:8545   -> 可以查看/etc/hosts文件中有一行 127.0.0.1   localhost

MetaMask成功连接到本地网后,再运行:

npm run start

会自动打开网页,并且弹出MetaMask;  

然后上传一张本地图片,之后点击"图片哈希写入区块链"按钮

IPFS入门实践_第6张图片

运行结果1

最终效果如图:

IPFS入门实践_第7张图片

运行结果

访问IPFS网关:
https://ipfs.io/ipfs/QmbHptfJfyuGAZxstFYgAVfz33cytR1seTD3ZabBSDd899

发现图片已经成功写入IPFS,如图:

IPFS入门实践_第8张图片

运行结果3

备注:本地IPFS网关端口默认为8080,我的电脑上端口冲突了,系统自动修改为8082。

 

参考

1. https://docs.ipfs.io/introduction/usage/ 

2. IPFS简介和入门实践

 

你可能感兴趣的:(IPFS入门实践)