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/<HASH>/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 <that hash>

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


View it:
$ipfs cat <the-hash-you-got-here>


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 <the-hash-here>
  ipfs ls <the-hash-here>/bar
  ipfs cat <the-hash-here>/baz
  ipfs cat <the-hash-here>/bar/baz
  ipfs cat <the-hash-here>/bar
  ipfs ls <the-hash-here>/baz

Get:

  ipfs get <the-hash-here> -o foo2
  diff foo foo2


Objects:

  ipfs object get <the-hash-here>
  ipfs object get <the-hash-here>/foo2
  ipfs object --help


Pin + GC:

  ipfs pin add <the-hash-here>
  ipfs repo gc
  ipfs ls <the-hash-here>
  ipfs pin rm <the-hash-here>
  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 <hash-of-remote-object>


Mount:

  (warning: fuse is finicky!)
  ipfs mount
  cd /ipfs/<the-hash-here>
  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 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

 

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"进行智能合约的部署

Remix-IDE部署智能合约

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 (
    <div className="App">
    <div style={{marginTop:10}}>智能合约地址:</div>
    <div>{this.state.address}</div>
    <div style={{marginTop:10}}>上传图片到IPFS:</div>
    <div>
      <label id="file">选择图片</label>
      <input type="file" ref="file" id="file" name="file" multiple="multiple"/>
    </div>
    <button style={{marginTop:10}} onClick={() => {
        var file = this.refs.file.files[0];
        var reader = new FileReader();
        reader.readAsArrayBuffer(file)
        reader.onloadend = function(e) {
          console.log(reader);
          saveImageToIPFS(reader).then((hash) => {
            console.log(hash);
            this.setState({imageHash: hash})
          });
      }.bind(this);
  }}>开始上传</button>

  <div style={{marginTop:10}}>图片哈希值:{this.state.imageHash}</div>
  <button onClick={() => {
       contractInstance.set(this.state.imageHash, {from: account}).then(() => {
          console.log('图片的hash已经写入到区块链!');
          this.setState({isSuccess: true});
      })
  }}>图片哈希写入区块链</button>

  {
    this.state.isSuccess
      ? <div style={{marginTop:10}}>
          <div>图片哈希成功写入区块链!</div>
          <button onClick={() => {
              contractInstance.get({from: account}).then((data) => {
                console.log(data);
                this.setState({blockChainHash: data});
              })
            }}>从区块链读取图片哈希</button>
        </div>
      : <div/>
  }
  {
    this.state.blockChainHash
      ? <div style={{marginTop:10}}>
          <div>从区块链读取到的哈希值:{this.state.blockChainHash}</div>
        </div>
      : <div/>
  }
  {
    this.state.blockChainHash
      ? <div style={{marginTop:10}}>
          <div>访问本地文件:</div>
          <div>{"http://localhost:8082/ipfs/" + this.state.imageHash}</div>
          <div>访问IPFS网关:</div>
          <div>{"https://ipfs.io/ipfs/" + this.state.imageHash}</div>
          <img alt="" style={{width: 100, height: 100 }} src={"https://ipfs.io/ipfs/" + this.state.imageHash}/>
        </div>
      : <img alt=""/>
    }
    </div>);
  }
}

export default App

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

 

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

小激动

 

但是我们看到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;  

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

运行结果1

最终效果如图:

运行结果

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

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

运行结果3

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

 

参考

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

2. IPFS简介和入门实践

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IPFS(InterPlanetary File System)是一个基于内容寻址的、分布式的、新型超媒体传输协议。IPFS支持创建完全分布式的应用。它旨在使网络更快、更安全、更开放。IPFS是一个分布式文件系统,它的目标是将所有计算设备连接到同一个文件系统,从而成为一个全球统一的存储系统。某种意义上讲,这与Web最初的目标非常相似,但是它是利用BitTorrent协议进行Git数据对象的交换来达到这一个目的的。IPFS正在成为现在互联网的一个子系统。IPFS有一个更加宏伟而疯狂的目标:补充和完善现有的互联网,甚至最终取代它,从而成为新一代的互联网。这听起来有些不可思议,甚至有些疯狂,但的确是IPFS正在做的事情。图1-1所示为IPFS的官方介绍。 图1-1 IPFS官方介绍IPFS项目通过整合已有的技术(BitTorrent、DHT、Git和SFS),创建一种点对点超媒体协议,试图打造一个更加快速、安全、开放的下一代互联网,实现互联网中永久可用、数据可以永久保存的全球文件存储系统。同时,该协议有内容寻址、版本化特性,尝试补充甚至最终取代伴随了我们20多年的超文本传输协议(即HTTP协议)。IPFS是一个协议,也是一个P2P网络,它类似于现在的BT网络,只是拥有更强大的功能,使得IPFS拥有可以取代HTTP的潜力。Filecoin是运行在IPFS上的一个激励层,是一个基于区块链的分布式存储网络,它把云存储变为一个算法市场,代币(FIL)在这里起到了很重要的作用。代币是沟通资源(存储和检索)使用者(IPFS用户)和资源的提供者(Filecoin矿工)之间的中介桥梁,Filecoin协议拥有两个交易市场—数据检索和数据存储,交易双方在市场里面提交自己的需求,达成交易。IPFS和Filecoin相互促进,共同成长,解决了互联网的数据存储和数据分发的问题,特别是对于无数的区块链项目,IPFS和Filecoin将作为一个基础设施存在。这就是为什么我们看到越来越多的区块链项目采取了IPFS作为存储解决方案,因为它提供了更加便宜、安全、可快速集成的存储解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值