|
|
本帖最后由 赤膊医数 于 2021-4-22 23:41 编辑 7 M$ O/ \& F2 ?* {
; ^) w9 s. ?" H2018年,最火爆且值得期待的区块链项目莫过于EOS和IPFS。1、IPFS简介- IPFS是什么
; z5 ~# N( Z" {6 ?# p星际文件系统IPFS(InterPlanetary File System)是一个面向全球的、点对点的分布式版本文件系统,目标是为了补充(甚至是取代)目前统治互联网的超文本传输协议(HTTP),将所有具有相同文件系统的计算设备连接在一起。原理用基于内容的地址替代基于域名的地址,也就是用户寻找的不是某个地址而是储存在某个地方的内容,不需要验证发送者的身份,而只需要验证内容的哈希,通过这样可以让网页的速度更快、更安全、更健壮、更持久。8 N7 }+ ~2 d, R2 _
以上内容来自巴比特官网介绍
+ P2 t- e2 x D' w1 C( qIPFS是基于区块链技术的去中心化存储网络,实现了永久性存储。1 O5 S$ d8 M- j: D* j
- IPFS的火热/ H: N7 K6 B- a
Filecoin ICO是迄今为止涉及金额最大的ICO,仅一小时就募集了接近2亿美元,打破ICO记录,成为2017年最火爆的区块链项目。IPFS项目吸引了世界各地数字货币投资者和互联网从业者的密切关注,2018年比较值得期待的是IPFS主网的上线。然而就在前段时间,官方公布说上线时间延期到年底。
: A* s# H$ N" _, {. `+ d( D( n注:Filecoin是IPFS激励层的加密数字货币(即代币),有点类似于以太坊平台上的以太币。7 K, P& ]) J [# R; q
IPFS官网:https://ipfs.io/
- E' x3 j# N: `6 mFilecoin官网:https://filecoin.io/
" m$ y( g& Z1 P' Q" s - IPFS的应用案例
7 p- L1 U6 p+ ]( ]7 u* AGitHub有两款开源项目,且有对应网址,分别是音乐播放器和视频播放器。
. X( X" U: c) J0 A( s; r3 ]2 A) s1 b9 I3 {; n
- IPFS音乐播放器
$ V2 Y" U0 S. x- Z" p: y3 H8 D( A& G' f0 ^6 v0 s9 S9 u# {3 v+ L
# V) U, D! G& J
8 `3 ^9 g/ A/ P
5 l9 N5 ?8 y6 a- u$ AIPFS音乐播放器7 L7 E; u6 @4 ?5 W3 q) m8 I
: h+ {' U/ \* b; C1 U( [/ UIPFS音乐播放器网址:https://diffuse.sh/9 @6 h+ |2 k% Q; [% U' U, M
GitHub地址:https://github.com/icidasset/diffuse
3 A- J/ B& ]# f l3 j - IPFS视频在线播放器* U/ H/ m. t; J |! _* R
1 O0 Z4 c7 ^5 E) O- X
9 w" C' {& T- ?+ Y3 Y' x
) k. l8 R7 P% l
# a. y+ P; k! f; R/ G5 oIPFS视频在线播放器首页+ |) A$ ^, `+ N
: X: s: ]* }" {$ d, i8 R+ f
, k6 P7 G3 }* S/ D' ]- p
- X8 k4 X$ }5 S, d, v) _
O7 { X% }6 @4 `# P0 O6 s8 @
( n, n* ~* e. S& x/ T' d! rIPFS视频在线播放器播放电影
; f: G" n' h7 Z
) [; N/ f% T/ U/ N! K4 H6 E号称是国内第一个IPFS应用
5 C4 _5 }1 B' ]5 `# I @5 ~IPFS视频在线播放器网址:http://www.ipfs.guide/8 }- `8 X# R( ^4 j1 h* c6 v
GitHub地址:https://github.com/download13/ipfstube
( ?1 \; x& B( V9 }( \1 @+ I3 ]$ U可用于测试的电影视频Hash(这里只列举两部):! C% H9 `% z' {& c) j
神秘巨星:QmWBbKvLhVnkryKG6F5YdkcnoVahwD7Qi3CeJeZgM6Tq68
' j1 X9 ^8 z6 e- v3 D盗梦空间:QmQATmpxXvSiQgt9c9idz9k3S3gQnh7wYj4DbdMQ9VGyLh0 R% ^* U( p9 }6 |, |0 R
2、IPFS的安装既然IPFS这么牛,有必要了解一下IPFS的开发,先从IPFS的安装开始。
5 Z& L" h; m$ T/ n/ a7 Z* I% T' `, Z- IPFS Desktop
+ l8 `0 N1 u8 |& K W! R7 ^当然,可以直接安装IPFS节点桌面管理软件来体验一下。该软件可以方便地运行和管理自己的节点,查看IPFS节点资源信息,支持二次开发。该项目是Node.js编写的,已开源。8 W% q% Z0 `8 d+ x& v. @# L
3 A0 u4 ~0 U q. _: ?8 H& m
9 s. N/ o1 |3 |2 s$ }
* M) i$ t$ \# T( {
" Y, ]6 Q$ m8 M7 H9 j- ]3 S1 UIPFS节点桌面管理软件& @8 t4 R( j$ ~/ N8 b6 Q
+ W) J& ]: k* k: J* I4 X% @GitHub地址:, |( s& T w- Y1 v
https://github.com/ipfs-shipyard/ipfs-desktop
3 ^1 A0 L( N' \1 F7 O9 S1 n - Go-IPFS
. ]' ], ^" O8 ^: `# H5 l进入IPFS的官网,找到并切换到"Install"页面,点击"Download IPFS for your platform",会跳转到如下网址(需要翻墙):
! A& y+ P3 q9 Ohttps://dist.ipfs.io/#go-ipfs
/ \) K8 r9 G* Z% D3 n; G7 b" c+ T+ ?+ k: g1 M7 f! D: d d' f5 @; i
2 R7 ^4 F1 l0 e0 o
9 ~9 [$ j; e1 s1 X! Q下载Go-IPFS
2 E/ i$ B" |5 J+ Z/ K6 g I
9 H3 h5 r: v6 r0 N( s+ ]6 o' f如果打不开,可以试着去Github查看安装方法) p: T% l- [1 F, ~; Q5 m! F
GitHub地址:https://github.com/ipfs/go-ipfs
9 P/ C# X9 ~) F: K3 {将网页下载好的文件解压出来,下载的是"go-ipfs_v0.4.13_darwin-amd64.tar.gz",解压出来的是go-ipfs文件夹,
. X0 U6 x' j, Y3 v然后打开终端,进入到go-ipfs文件夹根目录,复制ipfs文件到系统的bin目录,然后可以通过"ipfs version"来检查,操作如下:
% w& h v7 n- T# W* p5 twenzildeiMac:go-ipfs wenzil$ pwd/Users/wenzil/Desktop/study/go-ipfswenzildeiMac:go-ipfs wenzil$ lsLICENSE README.md build-log install.sh ipfswenzildeiMac:go-ipfs wenzil$ cp ipfs /usr/local/bin/ipfswenzildeiMac:go-ipfs wenzil$ ipfs versionipfs version 0.4.137 A9 ]. {) f w' Q: |- i# O
3、IPFS节点的创建、查看和启动以下是安装官网的Go-IPFS步骤下实验的
2 H6 Q5 C# T# }! d2 ?- 创建节点
i. q1 G" K( g5 y( ?: a进入到当前用户的根目录,并使用"ipfs init"命令创建节点,可以用"open ./"打开创建节点生成的".ipfs"目录。
6 Q/ S9 t. ~ P7 X, @! q" Q, pwenzildeiMac:go-ipfs wenzil$ cd ~/wenzildeiMac:~ wenzil$ pwd/Users/wenzilwenzildeiMac:~ wenzil$ ipfs initinitializing IPFS node at /Users/wenzil/.ipfsgenerating 2048-bit RSA keypair...donepeer identity: QmWH4xmGBznY9CJ4SjxpxWqGwMwrFtPdjgeweLCfJxW8j9to get started, enter: ipfs cat /ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/readmewenzildeiMac:~ wenzil$ cd .ipfswenzildeiMac:.ipfs wenzil$ open ./
, F: b( L7 a* ?4 ?
5 g/ a9 N( R/ X! E2 C9 U0 r! ]3 t
2 O6 o. E. Y4 @' [
1 u7 ^8 K! \5 J* @2 }8 m
IPFS节点的创建# j5 z/ p" W. ^' p
. j$ m4 S! d3 j# @- 查看节点id- A( _6 @& k: w: h
wenzildeiMac:.ipfs wenzil$ ipfs id{ "ID": "QmWH4xmGBznY9CJ4SjxpxWqGwMwrFtPdjgeweLCfJxW8j9", "PublicKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt98O5zNptBtmSF6xYdOHAMunQsXE9rAmgqBXVPLJk+AoaBjNiAipB+sTXKwaj8stp9c3iuSzz10+dyYI38bq4TPDCsHnQ3PjKSgZwEaT0M6pJhGqJcSbLY57CjQOEwgFe+tw3b4hcoDvvNJMG0dZZg1r9xnfevBz0DNewlj2vtviSTQL6r/ZXlD04GsytxTSQ2pzMJTG3QmYyokeZ37DT7Vwa+IJjDCiDJC5BlZ204zunZBx3tqWUn2Hr2NtEX+4YDdX4SBHa0ZDNqZmzLRe5YlAXjVI0ONHs+BVsC1v1L5we52iSYCSgVHoxRP/pa9EZdHMvgs9QeAa5jO90yxgTAgMBAAE=", "Addresses": null, "AgentVersion": "go-ipfs/0.4.13/", "ProtocolVersion": "ipfs/0.1.0"} - 修改IPFS默认存储空间
# S! f, ~1 X# N: E存储节点默认存储大小为10G,如果你想修改存储空间,可以修改config配置文件,找到StorageMax并修改' m6 K3 n( w- _1 }
wenzildeiMac:~ wenzil$ export EDITOR=/usr/bin/vimwenzildeiMac:~ wenzil$ ipfs config edit ; ~- ~$ j2 \4 v- a
) ~; b! J: F2 `, Q* F0 g ~: m/ V" f G: E8 c
修改IPFS默认存储空间
. Y/ s8 ? N; I
5 g8 v, Z0 d3 |2 ~ - 启动和同步节点服务器
; P+ v* {2 M2 P5 h, P6 P$ C5 f执行"ipfs daemon"命令,可以同步节点数据到IPFS网络。
9 w; M- X: r0 y( U& OwenzildeiMac:.ipfs wenzil$ ipfs daemonInitializing daemon...Adjusting current ulimit to 2048...Successfully raised file descriptor limit to 2048.Swarm listening on /ip4/127.0.0.1/tcp/4001Swarm listening on /ip4/192.168.1.100/tcp/4001Swarm listening on /ip6/::1/tcp/4001Swarm listening on /p2p-circuit/ipfs/QmWH4xmGBznY9CJ4SjxpxWqGwMwrFtPdjgeweLCfJxW8j9Swarm announcing /ip4/100.64.9.179/tcp/55898Swarm announcing /ip4/127.0.0.1/tcp/4001Swarm announcing /ip4/192.168.1.100/tcp/4001Swarm announcing /ip6/::1/tcp/4001API server listening on /ip4/127.0.0.1/tcp/5001Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8082Daemon is ready. V3 ^" f5 o& O5 K$ A" d+ l" G. V
4、IPFS运行体验- IPFS查看ReadMe* s4 o7 h7 ~+ f) A X
可以回去查看执行"ipfs init"命令的时候,返回的内容。打开一个新的终端,操作如下:7 _8 r, |: E4 u! o5 O
wenzildeiMac:~ wenzil$ ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readmeHello and Welcome to IPFS!██╗██████╗ ███████╗███████╗██║██╔══██╗██╔════╝██╔════╝██║██████╔╝█████╗ ███████╗██║██╔═══╝ ██╔══╝ ╚════██║██║██║ ██║ ███████║╚═╝╚═╝ ╚═╝ ╚══════╝If you're seeing this, you have successfully installedIPFS and are now interfacing with the ipfs merkledag! -------------------------------------------------------| Warning: || This is alpha software. Use at your own discretion! || Much is missing or lacking polish. There are bugs. || Not yet secure. Read the security notes for more. | -------------------------------------------------------Check out some of the other files in this directory: ./about ./help ./quick-start <-- usage examples ./readme <-- this file ./security-notes - Web管理界面 ]9 G/ O- l- X& x, T5 X
IPFS节点服务器启动后,可以用浏览器访问:http://localhost:5001/webui
" X. I: I3 w% u/ r5 `( z有本地配置、节点连接、本地节点文件等信息,如图:
7 k7 w$ v! |9 D3 h) K1 w, K
* A' Q5 v' u: t7 U
" E F* n, P, ]4 k+ y2 l2 L. G
, m2 t* ~6 |5 l0 x; y( g8 D- u( m
9 j6 c8 r; R) x8 H4 Y; h% PIPFS的Web管理界面
, W6 t/ g9 H i' q0 p
% d- L8 L4 |) o/ |6 h6 @
3 D7 T8 z9 B: b6 Y/ A5 F9 {- C$ F/ ~5 }7 {6 `1 m1 ?4 U8 ^1 e
5、设置跨域资源共享当我们在前端通过js接口操作ipfs时,会遇到跨域资源访问问题,可以在终端执行以下配置来解决:2 w! Q# M! S1 T1 v5 U2 ` d# m
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT","GET", "POST", "OPTIONS"]'ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials '["true"]'ipfs config --json API.HTTPHeaders.Access-Control-Allow-Headers '["Authorization"]'ipfs config --json API.HTTPHeaders.Access-Control-Expose-Headers '["Location"]'6、IPFS的基本操作6.1 添加单个文件到IPFS节点- 新建文件* Z) D8 q6 `9 p
wenzildeiMac:ifps_test wenzil$ vi test.txtwenzildeiMac:ifps_test wenzil$ cat test.txt IPFS测试文件 - 添加文件到IPFS节点- z L6 n2 C4 y/ |+ t0 t+ g! i! a
wenzildeiMac:ifps_test wenzil$ ipfs add test.txt added QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab test.txt添加文件到IPFS节点后,返回了文件的哈希值
2 g* g$ |. V# O1 j$ p. j! Y - 查看IPFS节点的文件3 w# B8 d# |, \
wenzildeiMac:ifps_test wenzil$ ipfs cat QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2AbIPFS测试文件注意:此时的文件只是添加到了本地的IPFS节点,读取的是本地数据,可以通过如下网址查看。2 \& I* u4 m, ]( |$ R8 L# l
http://localhost:8080/ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab7 Q5 E* R. o, @ ~! o0 }
通过"ipfs daemon"命令启动节点服务器,会将本地节点文件同步到外网,同步成功后,这时就可以访问如下网址来查看(如果访问失败,试着翻墙看看)。
& z1 e9 }8 G+ Dhttps://ipfs.io/ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab
0 Q6 r: I) O$ V$ y( Z2 W/ p$ d! s& J N& b' z& S. v6 z! {) H: W" m
, C% G v2 T6 ?9 U
% ]3 ?. \: d6 j3 Z$ h
查看IPFS文件内容( z6 H2 x! [! R4 Z9 c! N
& e! Q- E, `2 ]( C) M( h
如果访问成功的话,说明已经存储到IPFS网络中。目前IPFS网络暂未加入代币Filecoin机制,所以存储读取文件免费,速度也比较慢。4 J9 Z5 L6 ~; h3 @
- 下载IPFS节点的文件9 T1 }& R" `7 b" L
wenzildeiMac:ifps_test wenzil$ ipfs get QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2AbSaving file(s) to QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab 25 B / 25 B [========================================================] 100.00% 0s查看当前目录,发现多了一个"QmSV..."的文件"
?: M6 }) p i6 a5 p- M9 {) o9 } w8 L
6 X5 w7 }! ]8 Z# D5 @$ ]! {
; E# m' i/ [3 n! ^
* r c! f" r* [3 ^
下载IPFS节点的文件
& P8 q8 Q- t5 i
3 `; E9 A' u" h) s5 x8 h
2 |0 p2 h$ |( ] 6.2 创建文件夹存储文件- ipfs命令新建文件夹7 L+ {9 V* t& p) w" }
wenzildeiMac:ipfs_test wenzil$ pwd/Users/wenzil/Desktop/study/ipfs_testwenzildeiMac:ipfs_test wenzil$ ipfs files mkdir /wenzilwenzildeiMac:ipfs_test wenzil$ ipfs files cp /ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab /wenzil/test.txtwenzildeiMac:ipfs_test wenzil$ ipfs files lstestwenzilwenzildeiMac:ipfs_test wenzil$ ipfs files ls /testwenzilwenzildeiMac:ipfs_test wenzil$ ipfs files rm -rf /testwenzildeiMac:ipfs_test wenzil$ ipfs files lswenzilwenzildeiMac:ipfs_test wenzil$ ipfs files ls /wenziltest.txtwenzildeiMac:ipfs_test wenzil$ ipfs files read /wenzil/test.txtIPFS测试文件注:"ipfs files rm -rf /文件夹名"可以删除文件夹。* r/ z, s0 @0 w
& r4 T4 `8 ]- c7 C& S- g 6.3 IPFS上传文件夹- ipfs命令添加文件夹7 k6 v: g0 \3 P
先在本地创建一个文件夹和对应文件,如图:- m6 ?8 c5 }; }7 |/ }3 l; @
) I0 Z4 k, |* s, f( K7 \$ r p$ I( i( ^! J8 b
n1 Y3 Z1 |" F- `% X6 K6 d* g3 S! f$ ]$ ?
本地创建文件夹及文件
8 B- h, s" W/ |2 D0 }% P, ^ @( {% ^. c" @
然后通过"ipfs add -r 文件夹"命令添加整个文件夹
" c! x. V' w- {! s wenzildeiMac:ipfs_folder wenzil$ pwd /Users/wenzil/Desktop/study/ipfs_folder wenzildeiMac:ipfs_folder wenzil$ ls portrait.jpeg readme.txt wenzildeiMac:ipfs_folder wenzil$ cd .. wenzildeiMac:study wenzil$ pwd /Users/wenzil/Desktop/study wenzildeiMac:study wenzil$ ipfs add -r ipfs_folder/ added QmbHptfJfyuGAZxstFYgAVfz33cytR1seTD3ZabBSDd899 ipfs_folder/portrait.jpeg added QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQv T ipfs_folder/readme.txt added QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj ipfs_folder wenzildeiMac:study wenzil$ - 查看文件夹的文件内容
8 H! M9 s; A* l l3 U1 Q5 qwenzildeiMac:study wenzil$ ipfs cat QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQvT 我是区块链开发小白,请大家多多赐教,谢谢。欢迎阅读我的区块链系列文章,简书地址:https://www.jianshu.com/u/5f809ab3698cwenzildeiMac:study wenzil$ ipfs cat /ipfs/QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQvT我是区块链开发小白,请大家多多赐教,谢谢。欢迎阅读我的区块链系列文章,简书地址:https://www.jianshu.com/u/5f809ab3698cwenzildeiMac:study wenzil$ ipfs cat /ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj/readme.txt我是区块链开发小白,请大家多多赐教,谢谢。欢迎阅读我的区块链系列文章,简书地址:https://www.jianshu.com/u/5f809ab3698c - 查看IPFS对应文件夹
& `9 }" G% W/ O, l: r# ~访问文件夹对应的IPFS地址:
m0 w3 Z9 t9 g; A/ L8 f8 ~https://ipfs.io/ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj
( a9 ~/ C4 g0 B第一次访问的时候,需要同步数据到IPFS网络,等待时间有点久,慢到让你以为同步失败了。
7 ^- P$ Q6 X H: ^: ~6 t" b2 o3 s2 |/ A7 N* I
- l$ O/ K3 d4 N/ {" b6 I
, K5 \( M1 X o' y Y3 A
查看IPFS对应文件夹 s a( T6 d8 m9 d" U- D
# k @: a A6 S" O1 [- Z* P* p访问文件夹对应的文件,如看到图片文件,访问ipfs网关:/ `. v9 z2 Y9 {6 n* P6 Z' t$ p
https://ipfs.io/ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj/portrait.jpeg, m# X7 P7 l4 F2 o/ J' O
: a" f9 F& E- `( d: u6 W# r
: m, _1 R, r& Y5 F1 \( x2 P f3 }6 c$ p/ b
查看IPFS文件夹对应文件
6 G8 V$ A* g9 s; ?3 A% a% V% V0 U E* s& o
或者通过文件的Hash来访问,如访问txt文件的地址: r5 }3 Z+ h+ N4 G' a; ?
https://ipfs.io/ipfs/QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQvT! P5 g) I3 b: R* l
: x& ^3 N# v& M9 r, `' Q" s
) X1 c" q! f5 N, O1 n$ ^# `2 Z2 I- }6 j {9 b6 i
通过文件Hash访问查看
; k7 v: C. E" B6 k
1 {' N) E' i! p$ D6 I
. d: [0 ^( Q+ E& ?9 l3 O 6.4 添加简单网页到IPFS节点- 网页效果和项目结构, L( N4 K8 ?% r. @6 ^
实现一个简单的实时显示系统当前时间的网页,效果如图:
, W. P" R9 x$ R$ {" ^6 }* t" i9 N
P+ r7 N2 t) r f4 ]1 d9 B& ]" U7 x0 M$ V2 @* t
* }% W/ U2 i: u% ?1 H- E& h
4 c) h9 B V- a0 q' VIPFS添加简单网页
3 c" N6 V$ Z" ^: U+ [5 U4 Y% }/ ?: w% ` u# D: D
工程结构如图:
% `2 x* `$ l/ \7 S+ k( `) e% v0 I9 ^) H
1 \+ j- z) j; a( n) E. s
0 r7 T7 g# z$ M, t+ z1 P% s
! F6 C* j' ^/ q8 z( P; r, A网页工程结构
9 s/ ^* y* v% Q- z& f6 ]0 \; K' W. A& e: B% X' L) \
$ L8 J3 E! P9 _5 z! m* {# y
实现代码比较简单,这里就不贴代码了。
4 I0 N T( Z( O6 A- ipfs命令添加文件夹: H f+ j1 i3 _& T
wenzildeiMac:study wenzil$ ipfs add -r ipfs_htmladded QmTj49dgFgFhfNRTUYyUSzk3puj7vvDoVsAynFrL7GAj1d ipfs_html/index.htmladded QmeHFBSyN9KqeZWKyKTWKYzDRU192YWDRjf6sLWFWhwk2z ipfs_html/styles.cssadded QmWkEfgL2pjo7n8b9YBCv4qwE77YWePkSscxiHQfPpwpkp ipfs_html/time.jsadded QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD ipfs_html记得要开启IPFS节点服务器进行数据的同步,可以使用"ipfs daemon"命令在新的终端窗口打开运行。6 ?" T3 V; C0 o, G) M3 T
wenzildeiMac:~ wenzil$ ipfs daemonInitializing daemon...Adjusting current ulimit to 2048...Successfully raised file descriptor limit to 2048.Swarm listening on /ip4/127.0.0.1/tcp/4001Swarm listening on /ip4/192.168.6.31/tcp/4001Swarm listening on /ip6/::1/tcp/4001Swarm listening on /p2p-circuit/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrzSwarm announcing /ip4/127.0.0.1/tcp/4001Swarm announcing /ip4/192.168.6.31/tcp/4001Swarm announcing /ip6/::1/tcp/4001API server listening on /ip4/127.0.0.1/tcp/5001Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8082Daemon is ready - 访问ipfs对应文件9 |7 N$ Z6 B' ?5 u2 Q) ^
浏览器访问ipfs网关:% d+ c0 l" X( O- e1 x$ ~
https://ipfs.io/ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD/
7 k$ ?$ P6 S4 B, x
& @* @* Y+ f1 J; W- @% {
; y) o2 ?; ^0 B `7 ^
; }: i( C. H* ^/ @4 s) D查看IPFS对应网页# `" p( X# A3 K0 _7 ?" S; g
' i* c7 l7 c6 `+ X, p G4 @
) L/ _1 v2 w* v5 C' U% T
6.5 IPNS绑定节点名- IPNS绑定节点操作
5 B% V4 Y# C. d7 R6 j每次修改文件内容后,文件的哈希值就会发生变化。对于网站而言,发布后可能还需要做修改,这时需要IPNS绑定节点名。每次更新网站内容后,重新publish一次更新发布到IPNS即可。8 B- x7 C4 M& N- A
刚才的html根目录的哈希值是QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD,操作如下:! R% @+ y7 ~1 c: d* c
wenzildeiMac:study wenzil$ ipfs name publish QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDDPublished to QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz: /ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD - 查看当前节点
+ d! s/ l7 Y8 T" w$ O! T. H4 twenzildeiMac:study wenzil$ ipfs id{ "ID": "QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "PublicKey": "CAASpg......", "Addresses": [ "/ip4/127.0.0.1/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip4/192.168.6.31/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip6/::1/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip4/14.xxx.xxx.xxx/tcp/4001/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz", "/ip4/61.xxx.xxx.xxx/tcp/20472/ipfs/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz" ], "AgentVersion": "go-ipfs/0.4.13/", "ProtocolVersion": "ipfs/0.1.0"} 发现"ID"和上面"Published to"返回的节点一致,都是"QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz"
& \& G6 t5 X* x8 n - 验证节点
! f! H2 i/ i7 G) Q4 C命令为:"ipfs name resolve 节点ID“8 T3 T$ `8 m! `( U
wenzildeiMac:study wenzil$ ipfs name resolve QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz/ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD - 访问IPNS对应文件
$ u: z; z0 m( T Q2 q& l9 e浏览器访问ipfs网关:- [9 u" n* Z6 T8 [
https://ipfs.io/ipns/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz/
8 }$ w" E$ N" z- Q5 l# K# H' h s9 C. q @& K' O% Z4 y
: w3 w5 c3 n B" f# [+ s; z9 f6 _# x
5 M- K5 P! X, I8 s, ?
3 R6 i- u& G7 S6 N- v/ {
查看IPNS对应网页
: O9 a5 K$ ~2 ~! G* _, \. ~) z$ B. i
7 t+ m7 G: u# n' @$ @7、IPFS与以太坊DApp开发实战- IPFS与以太坊DApp结合的好处- V# Q8 n5 o0 _- a( e
在以太坊平台上,往区块链写入数据需要花费以太币,调用智能合约执行每一行代码的时候,都需要一定量的gas交易费。区块链存储大数据成本很高,而且不合理。4 [1 E5 E' q4 u
可以先将文件存储到IPFS,然后得到文件的Hash存储到以太坊区块链中。读取文件的时候,从以太坊区块链中获取文件的Hash,再通过Hash来读取IPFS网络上的文件。1 e5 W8 ~) Y! L5 X8 u6 d
使用官方提供的ipfs-api,可以很方便地在代码中操作节点将数据上传到IPFS,或者通过Hash从IPFS读取数据。5 k- K2 l% O& ^! R* v
Truffle框架提供了快速搭建包含以太坊智能合约的React项目,可以通过"truffle unbox react"创建工程,然后安装ipfs-api依赖库。于是,可以在前端方便地调用IPFS的接口来读取、上传文件。* \4 ~( `7 Y; Y' [% G: ?
truffle unbox react官网: n: X7 F) r" T1 {9 c, o
http://truffleframework.com/boxes/react c1 u$ c1 T# [/ {; X
- IPFS与DApp开发实战* m6 u2 L% [ T1 H5 \0 o
话不多说,开始进入实战开发。$ W3 {( h5 `0 K! [) E/ P& x/ R
7.1 安装Truffle unbox react新建一个空目录"ipfs_dapp",然后执行安装命令
2 j" ^3 b" W; }truffle unbox reactwenzildeiMac:ipfs_dapp wenzil$ pwd/Users/wenzil/Desktop/study/ipfs_dappwenzildeiMac:ipfs_dapp wenzil$ truffle unbox reactDownloading...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 build7.2 安装ipfs-apinpm install --save ipfs-apiwenzildeiMac:ipfs_dapp wenzil$ npm install --save ipfs-apinpm WARN deprecated bignumber.js@6.0.0: Custom ALPHABET bug fixed in v7.0.2react-box@0.1.0 /Users/wenzil/Desktop/study/ipfs_dapp├—┬ ipfs-api@22.0.0 │ ├—— async@2.6.1 │ ├—— big.js@5.1.1 │ ├—┬ bs58@4.0.1 │ │ └—— base-x@3.0.4 # ...... 省略N多行输出7.3 修改智能合约代码修改contracts目录中的"SimpleStorage.sol",修改后完整代码:6 p$ c$ Y* ?* B# m0 P, |
pragma solidity ^0.4.18;contract SimpleStorage { // 用于存储图片的哈希值 string storedData; function set(string x) public { storedData = x; } function get() public view returns (string) { return storedData; }} 修改"Migrations.sol"
x$ L! q7 m$ H, cfunction Migrations() public { owner = msg.sender;}修改为:constructor() public { owner = msg.sender;}7.4 编译智能合约truffle compilewenzildeiMac:ipfs_dapp wenzil$ truffle compileCompiling ./contracts/Migrations.sol...Compiling ./contracts/SimpleStorage.sol...Writing artifacts to ./build/contracts7.5 部署智能合约进入remix-ide,复制SimpleStorage.sol代码,然后切换到"Run"菜单,选择"Injected Web3"进行智能合约的部署
_1 Z7 \8 m; Z
8 u/ Y2 r- }0 E+ W. t9 J' R& R
7 {: K( B) @8 J& z' n
8 ^, S' N+ o- P. b6 I U% E* L$ L( ERemix-IDE部署智能合约
# m1 m2 o" \* I. b5 _& b0 `* u& L
3 T% ?& w. h2 r! H* ^3 `
, G I# c5 @& O( G* }
' e; I X, d# I# m9 {2 t) C# Y
3 \" Y+ E, h9 wRemix-IDE部署智能合约-确认
+ i# `% H( Z. q, b) y! }3 `1 [
" f) F; }8 o! ~- l5 X4 B然后复制智能合约地址,App.js文件中会用到合约地址为:"0xb177d6cf6916f128c9931e610c63208d9c5a40f3"
; ?9 Q" a; H) d( U. B3 e1 G7.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 App7.6 新建终端,执行"npm start"命令,结果如图:
7 q9 `* R; B3 C {
5 h3 S2 y1 o, w& ~ K3 Y' z' k
8 ~! O1 ]& m, w4 s7 u* f6 S& hnpm_start6 c9 P: N1 O$ s! h9 b7 R) m7 u
) J" ?1 ]4 Y' B; S会自动打开网页,然后上传一张本地图片,之后点击"图片哈希写入区块链"按钮
- g3 Z2 [3 n0 R; O# Y5 e! H
- K+ K! y( x* U+ }8 @: Q5 U& l, k
- G1 C! c9 s; b$ m
% J8 X' f* K& B运行结果1
' [4 I" j! Q' h/ Q9 E
9 @/ k6 U* b! |; @$ [! h最终效果如图:; u1 a c ^5 a' x
) b3 q! n% W; C7 R& o$ ~
4 S+ x( g6 g2 w4 |3 y
2 @4 \3 {. |% f. {. ~. C* \$ L6 G) E4 H4 A) ~
运行结果& H/ O0 |( O6 u7 G1 n4 d" n5 l" L
- \8 w- y7 ]6 s. S
访问IPFS网关:+ C4 r8 c6 E1 g" ^
https://ipfs.io/ipfs/QmbHptfJfyuGAZxstFYgAVfz33cytR1seTD3ZabBSDd899* ^' f3 x! F. Y7 P6 P ]1 @8 b& Y3 [
发现图片已经成功写入IPFS,如图:
1 m/ d+ _# x$ ~' Y3 h5 D# @! A; _2 S# \
% u: @ P/ R9 R9 |& T% {
1 R& Z4 v% x2 C# }
7 J" k! h" W9 O$ v. `/ V运行结果3
6 c, A+ U4 i4 ?7 ]: t5 K/ ]7 t5 J3 ]! E
备注:本地IPFS网关端口默认为8080,我的电脑上端口冲突了,系统自动修改为8082。
' B" ^' e; M4 X* ^5 I" e/ u' z8 m搞定,收工。
6 z% U- o ~% ~$ K( z6 C1 l# XPS:刚入坑的小白,很多不懂,还请各位大佬多赐教,谢谢!% Z- k: u0 S, I
0 G$ @* } p8 R
|
|