|
|
本帖最后由 赤膊医数 于 2021-4-22 23:41 编辑 5 }7 E& k2 x+ V6 K" J% b
5 W7 U9 {' n; K& J
2018年,最火爆且值得期待的区块链项目莫过于EOS和IPFS。1、IPFS简介- IPFS是什么$ _1 I0 m# |6 y- [7 h
星际文件系统IPFS(InterPlanetary File System)是一个面向全球的、点对点的分布式版本文件系统,目标是为了补充(甚至是取代)目前统治互联网的超文本传输协议(HTTP),将所有具有相同文件系统的计算设备连接在一起。原理用基于内容的地址替代基于域名的地址,也就是用户寻找的不是某个地址而是储存在某个地方的内容,不需要验证发送者的身份,而只需要验证内容的哈希,通过这样可以让网页的速度更快、更安全、更健壮、更持久。
4 n8 w8 j# K/ w) u以上内容来自巴比特官网介绍( ~9 H6 _6 h/ b6 g* A
IPFS是基于区块链技术的去中心化存储网络,实现了永久性存储。4 h+ C1 Z+ M% B0 T
- IPFS的火热
% R2 X' b! x( I5 I& x' W0 ?; UFilecoin ICO是迄今为止涉及金额最大的ICO,仅一小时就募集了接近2亿美元,打破ICO记录,成为2017年最火爆的区块链项目。IPFS项目吸引了世界各地数字货币投资者和互联网从业者的密切关注,2018年比较值得期待的是IPFS主网的上线。然而就在前段时间,官方公布说上线时间延期到年底。* i2 }4 A3 x) z5 s
注:Filecoin是IPFS激励层的加密数字货币(即代币),有点类似于以太坊平台上的以太币。
! y0 {7 v2 O; A5 dIPFS官网:https://ipfs.io/
, W- e C f- B- T5 t4 _Filecoin官网:https://filecoin.io/( U7 o! f" z% @9 v- ~ o# _
- IPFS的应用案例
t/ P, l+ C5 c6 I e: W. ^6 d0 I7 ?GitHub有两款开源项目,且有对应网址,分别是音乐播放器和视频播放器。
1 h1 c' \! _6 j* f) D) Z9 h+ ^9 @, l7 \; h* j" ?( }- H8 Y
- IPFS音乐播放器5 V$ T" P! E$ l i7 W: x* m& ?
1 D( v- l% U% b: }4 D5 A. D: Q3 r( C, x# q9 Q8 {! i: z5 X- W+ s
' a& I+ l) o8 I/ |* O2 u: X7 F
9 T1 h/ b$ f8 H5 `IPFS音乐播放器4 E4 ]. k5 D2 _) k- S% o
$ }% A# l. F+ t1 C$ B1 yIPFS音乐播放器网址:https://diffuse.sh/
/ x+ x: { \! R: k# o0 o$ zGitHub地址:https://github.com/icidasset/diffuse6 k! F5 C# J, P9 H' i8 Y
- IPFS视频在线播放器
! E" L( Y' w7 b' d+ e1 n2 g' f4 G/ v# [' o! K
1 Z1 D) r( j% w' Y8 T/ r* e8 \
% f, _5 r8 S( B1 S+ V
! H$ S/ P# T+ r% M, [; jIPFS视频在线播放器首页
; d( J! S; Z& ]% y! W/ f4 _( ?8 m4 ~2 Q" F9 L
" q! U0 X+ |9 w6 J! L6 E! Q/ k
$ E& X c. j, M5 {! M# E2 L
4 i3 O! G( y8 b3 B# A1 d8 T4 Z7 q- H5 f' y# M0 x o
IPFS视频在线播放器播放电影* s# c; a& D$ Q9 q% U: ]
+ I9 O: x0 C7 w6 j( W3 @号称是国内第一个IPFS应用
+ T6 H; q2 D6 W% M3 pIPFS视频在线播放器网址:http://www.ipfs.guide/
- |5 N6 P: Y* eGitHub地址:https://github.com/download13/ipfstube- U5 G1 ]' i) D0 h* a" O
可用于测试的电影视频Hash(这里只列举两部):% E" z) Z7 M- c5 [0 D6 ^4 L7 d1 }$ s
神秘巨星:QmWBbKvLhVnkryKG6F5YdkcnoVahwD7Qi3CeJeZgM6Tq683 G- H' g% ^3 _; g" C8 S
盗梦空间:QmQATmpxXvSiQgt9c9idz9k3S3gQnh7wYj4DbdMQ9VGyLh# o/ {; l- |$ D& [
2、IPFS的安装既然IPFS这么牛,有必要了解一下IPFS的开发,先从IPFS的安装开始。
3 U5 O6 d+ S2 H: F0 R& _* _- IPFS Desktop& e* ?% X' S# x8 n3 G) y) \
当然,可以直接安装IPFS节点桌面管理软件来体验一下。该软件可以方便地运行和管理自己的节点,查看IPFS节点资源信息,支持二次开发。该项目是Node.js编写的,已开源。5 p0 j% j& ]. N
" g% N# c2 X$ t* l) _* P; `- i8 d; j) d/ E- t( v
' Q( u& J+ |. k! ]1 H
% A. ^4 w2 o; Z3 l% b D
IPFS节点桌面管理软件
, F& G" x; ]* x( |- D" F7 G$ }/ F- L% v5 y2 ?( ?5 ?
GitHub地址:
$ C& M' ?- T" H' W7 bhttps://github.com/ipfs-shipyard/ipfs-desktop3 ]- F) d/ P5 F; i) O( o* ~# @
- Go-IPFS
* T" m. @7 |- x6 a: E进入IPFS的官网,找到并切换到"Install"页面,点击"Download IPFS for your platform",会跳转到如下网址(需要翻墙):
" ^6 `+ f, Y% O& N i) @, [https://dist.ipfs.io/#go-ipfs
* W- `! y+ r. q# V/ _
, @+ c- R! O5 B+ O' }( m+ i4 a: Z% I
1 P/ d$ P3 i: g3 n
9 w$ a/ k r2 F下载Go-IPFS
3 \2 f" x8 D T/ j
& O: Z1 _$ B/ [ s5 e如果打不开,可以试着去Github查看安装方法
5 w# v; Y' U% {& RGitHub地址:https://github.com/ipfs/go-ipfs
% R+ F1 K9 E9 `+ q将网页下载好的文件解压出来,下载的是"go-ipfs_v0.4.13_darwin-amd64.tar.gz",解压出来的是go-ipfs文件夹,! ^! D% H" G+ s
然后打开终端,进入到go-ipfs文件夹根目录,复制ipfs文件到系统的bin目录,然后可以通过"ipfs version"来检查,操作如下:/ @7 S2 a) Z' d1 D- K! Z) y
wenzildeiMac: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.13! ]3 ^/ T9 P9 ?) K- L+ V# r
3、IPFS节点的创建、查看和启动以下是安装官网的Go-IPFS步骤下实验的6 Q W% k$ J& [: k$ G0 d5 [
- 创建节点' Z. w7 @% h' k& z0 B
进入到当前用户的根目录,并使用"ipfs init"命令创建节点,可以用"open ./"打开创建节点生成的".ipfs"目录。& k2 s" {( W5 h4 x
wenzildeiMac: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 ./
& n! a/ t! O3 `% T8 V
# R, g: Q1 A) m: P) Q+ W& S5 s
. D0 k7 L: [1 q9 V; `
6 |% M! U4 s, W- O; EIPFS节点的创建
8 w6 ]) c! y" v" g, k4 v( x5 j2 F4 G. I0 k6 I+ {
- 查看节点id
) E4 [6 b" U6 z+ CwenzildeiMac:.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默认存储空间3 { B* V+ U7 e0 d8 c/ m
存储节点默认存储大小为10G,如果你想修改存储空间,可以修改config配置文件,找到StorageMax并修改
: J4 o9 ?, {4 awenzildeiMac:~ wenzil$ export EDITOR=/usr/bin/vimwenzildeiMac:~ wenzil$ ipfs config edit 3 o* K9 c# N; Y3 L1 u4 G
2 M! _3 L }7 A/ v6 }
6 {4 w( j* A M0 }% r6 ]9 |" V修改IPFS默认存储空间" I, f3 Q, o2 f+ i, J7 h# ?( `
2 V) }( y# p0 N; ?8 Y# c2 x
- 启动和同步节点服务器
H- i( D) u7 ^; g执行"ipfs daemon"命令,可以同步节点数据到IPFS网络。
7 h( s# m. X/ }$ K. YwenzildeiMac:.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
/ A" i) }) k! A9 `. [- q8 C 4、IPFS运行体验- IPFS查看ReadMe
" g) ^3 H, a. e可以回去查看执行"ipfs init"命令的时候,返回的内容。打开一个新的终端,操作如下:
2 P5 E; [6 I8 M# |: TwenzildeiMac:~ 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管理界面 a6 R S* h, d/ `# `$ Z/ X3 Y
IPFS节点服务器启动后,可以用浏览器访问:http://localhost:5001/webui; }3 ~: y! o D+ d; `
有本地配置、节点连接、本地节点文件等信息,如图:1 @' G5 D( z/ L% w' n
& q' \; t2 ~" X0 k# e3 P8 R
8 m1 C7 b* \3 ]9 B1 n0 b: D
. k2 g) Q$ H0 e z! \* t
, r4 @0 S4 C, G V3 R! n. a! F2 Q2 H. l
IPFS的Web管理界面
) s' P5 a4 ^3 @! a0 d) p" {3 o7 a* i% ? v/ K! f
. G4 F4 e4 N, F, k
* [3 c" k1 V7 |2 X
5、设置跨域资源共享当我们在前端通过js接口操作ipfs时,会遇到跨域资源访问问题,可以在终端执行以下配置来解决:
# o$ Y% O4 H( @# sipfs 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节点- 新建文件& M* d9 @# K B$ ^) l/ X
wenzildeiMac:ifps_test wenzil$ vi test.txtwenzildeiMac:ifps_test wenzil$ cat test.txt IPFS测试文件 - 添加文件到IPFS节点2 e% r1 E w. a( ~( e' A
wenzildeiMac:ifps_test wenzil$ ipfs add test.txt added QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab test.txt添加文件到IPFS节点后,返回了文件的哈希值9 ?) ^3 y& ^4 y. _/ i
- 查看IPFS节点的文件: Y, z/ k- E# K$ H
wenzildeiMac:ifps_test wenzil$ ipfs cat QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2AbIPFS测试文件注意:此时的文件只是添加到了本地的IPFS节点,读取的是本地数据,可以通过如下网址查看。- {2 o1 N/ U& Z
http://localhost:8080/ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab& o& F* q8 f1 P# F
通过"ipfs daemon"命令启动节点服务器,会将本地节点文件同步到外网,同步成功后,这时就可以访问如下网址来查看(如果访问失败,试着翻墙看看)。8 G% c* E* H( i# s7 C% Q6 v! k, o! D
https://ipfs.io/ipfs/QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab
# Z4 M7 q; A) c9 I9 t: q% q0 I D* l% [6 I2 J3 N
3 H# A5 \0 g7 x9 P
9 K4 d( r$ I C6 X查看IPFS文件内容
2 j" y* G/ L4 T* ^
) i1 ~) S) k# u1 W% A1 `& j0 d% ~如果访问成功的话,说明已经存储到IPFS网络中。目前IPFS网络暂未加入代币Filecoin机制,所以存储读取文件免费,速度也比较慢。
5 v9 }5 C; o. S- w* Y, s - 下载IPFS节点的文件0 K5 b# ?# m* \3 I9 Q9 z2 `
wenzildeiMac:ifps_test wenzil$ ipfs get QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2AbSaving file(s) to QmSVKEwPBTzw5QLzGUE8oN8J1r4cadMeieSw4Co1ozm2Ab 25 B / 25 B [========================================================] 100.00% 0s查看当前目录,发现多了一个"QmSV..."的文件"+ w5 R0 ^; Y" i0 @4 q1 C. a9 e( G$ b2 p
- @: F! g2 l+ {+ j3 x, _' V
0 z- i& `1 j, q+ z8 y S
) N" H% v6 K9 K6 M& |% u* I- _1 l) W' O
下载IPFS节点的文件
% r( }7 q( K3 `8 e( ~+ |' \) G* \, n! c! A$ s3 c7 `
7 D+ n; j! z9 H) o; ^4 [ 6.2 创建文件夹存储文件- ipfs命令新建文件夹. a4 }: h! J, ]# E# c# Y' Y; J( Q
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 /文件夹名"可以删除文件夹。
y( c4 h; P3 ]5 G. o6 W. e E. ^! b, \) E
6.3 IPFS上传文件夹- ipfs命令添加文件夹4 k, C$ N; v8 @5 k
先在本地创建一个文件夹和对应文件,如图:
: N Q$ I4 c/ s2 i7 |6 j. H0 ~) W) {$ v0 i# A, w& H
7 I) a# J4 C# K. A [7 b. Z
1 {% p6 F2 n3 }" r; I
- y5 v9 }8 p! w5 `7 J. L& f/ p本地创建文件夹及文件
* G: E: C/ z7 e8 o, Z
) ^- C9 o$ c; B2 |/ M; R8 E3 u然后通过"ipfs add -r 文件夹"命令添加整个文件夹' o: d. @' X3 z w- T! v
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$ - 查看文件夹的文件内容0 d3 Q! c' h7 @, w
wenzildeiMac: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对应文件夹6 t5 ^5 j0 a% R4 U! `
访问文件夹对应的IPFS地址:, j# h* x; y) ]$ P5 \5 E. y& S4 U
https://ipfs.io/ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj1 I/ l; k/ b$ X% k
第一次访问的时候,需要同步数据到IPFS网络,等待时间有点久,慢到让你以为同步失败了。
. M/ A* I8 R1 e( g4 X
9 Z! C Q7 l7 i! C* \) R) p. o
3 L: w- `2 M9 Y# l! }( B" D" [. E" |8 r
查看IPFS对应文件夹
. ^2 u: _( L. Q( g& `- R* ^+ K
K3 o' r y$ D$ t4 R访问文件夹对应的文件,如看到图片文件,访问ipfs网关:
?4 `. A/ c/ x6 lhttps://ipfs.io/ipfs/QmdSd3xxKcwuMugyLCiLWzaeZKDkuM39R2tzyF3kBFDoaj/portrait.jpeg* d; x& b6 e2 [3 R
$ F5 K. P d: E O. R/ g
8 N9 L1 ?$ ~/ t' C! v) W
w9 O2 t- a* L7 t' D查看IPFS文件夹对应文件5 k1 A& h; `2 v; ]3 p+ |4 l
8 \& e6 g1 i$ S或者通过文件的Hash来访问,如访问txt文件的地址:) I8 \) M9 \5 y/ [2 R
https://ipfs.io/ipfs/QmPEWgwQEHD6qxm5cUivTEZ252T123DvQ5L6HyUDgViQvT
' f0 T1 E/ S' ^5 R4 `1 q
7 @. l% B, x1 v0 s0 x E
$ h8 {! {' j V9 @3 P
/ |7 }+ I/ j2 s7 h. e0 p* B通过文件Hash访问查看
9 b3 v r1 ^" }5 t
) x) `9 U0 i3 u$ \
; B. @* B! U5 `% d! T3 c4 I" p 6.4 添加简单网页到IPFS节点- 网页效果和项目结构
0 @; E: w) m0 W6 V+ s实现一个简单的实时显示系统当前时间的网页,效果如图:% ]- r, R3 {7 B! Z0 ^# O/ J
4 t6 o2 V, \$ }* d" N$ C7 |/ S) X" p! \4 x) l
6 F7 d1 o( w- h$ V$ n
/ `, m2 B4 a6 M* TIPFS添加简单网页- J3 M# ]% k$ p# O: N e3 ~1 b$ C
* t* B* ^4 w$ W$ ?' Z
工程结构如图:8 Y9 y, w0 B9 k9 y' j: b
% ]& m/ Q8 |) q0 a
1 \' x: L3 ?0 H: g( r% x* H
1 z6 K A5 ^# ?
- z( [! [; o5 K3 O: G+ R网页工程结构) S9 T5 J; d: _+ A
- A, k4 C. J$ k, q
) T! V3 C# d7 w
实现代码比较简单,这里就不贴代码了。
" D" ~( L$ N) I* D" ^" x- z5 }- ipfs命令添加文件夹
+ f; ]% G# K) CwenzildeiMac: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 b# o3 j$ }& g z6 Q/ ^2 YwenzildeiMac:~ 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对应文件
8 I; F0 s* B5 D; s A: L! [$ J浏览器访问ipfs网关:
, l- Q, O. `$ A4 o0 Q6 x+ uhttps://ipfs.io/ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD/9 i3 u! e# g b! r+ A( |
& W. J+ o' ~) m1 Q7 l# I+ I l& _
. ^2 `* H. E" H
" H, F( e. Q. s7 }- j9 i查看IPFS对应网页
( F5 U' ?+ M' r- c1 V
, ]; L2 H( v+ _$ Z% w' I2 [, |4 i' F7 \4 z& R& v
6.5 IPNS绑定节点名- IPNS绑定节点操作
0 R T" H( f# W& k6 [( @每次修改文件内容后,文件的哈希值就会发生变化。对于网站而言,发布后可能还需要做修改,这时需要IPNS绑定节点名。每次更新网站内容后,重新publish一次更新发布到IPNS即可。" p# h( ` E3 a' z
刚才的html根目录的哈希值是QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD,操作如下:
0 {+ R( V' L6 V% ^( p2 vwenzildeiMac:study wenzil$ ipfs name publish QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDDPublished to QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz: /ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD - 查看当前节点/ ^, i0 F7 H6 w: B; c
wenzildeiMac: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"
4 d# H, F) S, ~1 Z$ V - 验证节点
( x [% X/ A# M命令为:"ipfs name resolve 节点ID“8 k# a1 g+ C s7 s x
wenzildeiMac:study wenzil$ ipfs name resolve QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz/ipfs/QmeG6LKmEfF5s62cySE9ZnU8EifmU46CQTixipfzsZspDD - 访问IPNS对应文件
/ a$ |2 x/ L2 A6 k( v V$ U- t浏览器访问ipfs网关:
. U2 v& i; p$ d; d' v; Rhttps://ipfs.io/ipns/QmcXWJqPjCgr1wrReWu2zUT41E5FrrXp2uyyNZRr7jXXrz/
" e8 Q: w [' c. s- h3 G o3 f; I6 v# b# N, E
4 D( l0 T. M6 f( Z9 f; F% v6 X
: r% {( I |& a4 e9 ~' `* U" @, Z; W+ [* e0 ?
查看IPNS对应网页
3 ~! G9 ?) F; p* w4 E' b; ?4 A. N$ @' U; v( ^" j+ c
7、IPFS与以太坊DApp开发实战- IPFS与以太坊DApp结合的好处" m p5 \# g. ^* U4 y3 h7 G
在以太坊平台上,往区块链写入数据需要花费以太币,调用智能合约执行每一行代码的时候,都需要一定量的gas交易费。区块链存储大数据成本很高,而且不合理。! \2 ^5 L5 w9 X+ o
可以先将文件存储到IPFS,然后得到文件的Hash存储到以太坊区块链中。读取文件的时候,从以太坊区块链中获取文件的Hash,再通过Hash来读取IPFS网络上的文件。' _! [; x. T( Q' D5 J
使用官方提供的ipfs-api,可以很方便地在代码中操作节点将数据上传到IPFS,或者通过Hash从IPFS读取数据。+ l; K1 T" A! n8 Q4 p" }" R
Truffle框架提供了快速搭建包含以太坊智能合约的React项目,可以通过"truffle unbox react"创建工程,然后安装ipfs-api依赖库。于是,可以在前端方便地调用IPFS的接口来读取、上传文件。- l r4 Y3 j- b$ W& }
truffle unbox react官网:' y2 ~/ S- n; \' }3 d* ~1 f
http://truffleframework.com/boxes/react
& }- y' ?5 J- h3 l& a* b - IPFS与DApp开发实战
" Q( T! B5 E$ h" g( H话不多说,开始进入实战开发。
: e7 z" `* K5 J5 e7.1 安装Truffle unbox react新建一个空目录"ipfs_dapp",然后执行安装命令
; b' g7 V7 L7 X6 ~! d7 K( L! Dtruffle 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",修改后完整代码:
2 Q# i9 V; @; u% U! Epragma 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& N! C8 `# @7 l+ v D* W$ a( I
function 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"进行智能合约的部署
8 c1 M5 O k6 R4 {
' K7 R, o5 s2 a' \
% w: i3 R: N8 V5 K! k& r9 Y; t! a
% N7 |0 e3 ]+ ~& F% ^$ b3 l: VRemix-IDE部署智能合约
7 y: a) r2 _% a' g. s n- Z5 v" M) _- ]0 g$ R
$ h$ z, N( X3 k$ k4 Z0 r: I0 I
6 p1 v* d3 y( p" L
+ V5 L1 D3 G( M. V6 Z' ^Remix-IDE部署智能合约-确认) C7 j) b+ Y C# W9 e
6 K: M m5 U$ d9 Z; N# Z0 m
然后复制智能合约地址,App.js文件中会用到合约地址为:"0xb177d6cf6916f128c9931e610c63208d9c5a40f3"! u9 Q6 ]1 n! w }: H6 T
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 App7.6 新建终端,执行"npm start"命令,结果如图:. A! Q" F4 X N) I6 `. K
! B- a* Q! \2 C$ a0 ^
5 L. Y; }$ ~3 G/ V" y9 \
npm_start+ j3 U1 ~" x- r# C# k
# V. ]6 w5 h% r* U) T d# T/ F3 ]会自动打开网页,然后上传一张本地图片,之后点击"图片哈希写入区块链"按钮
" a, U* Z% f" i) j# h
# R0 j4 e2 T) T4 K! g# a
8 b; x3 g. M& @: B6 }$ u
% T" O7 x2 R+ n2 I运行结果19 \' y, B% u2 Y, c$ n5 [
$ q) _% T: ^' s2 e最终效果如图: n( ?* C! Y7 j2 R
/ j2 i. u1 P& \+ r2 I1 b) t" v
( R" h" ~* w7 J( k% {
1 T6 Q+ L! E1 Z# H0 |
% X% ~9 w' u5 B' Y* b运行结果3 R/ r9 F& j- D
! R- i+ ` ]) K# x+ b' `5 b, k访问IPFS网关:
- T7 Z ~3 M6 S+ e5 Y" T3 Ehttps://ipfs.io/ipfs/QmbHptfJfyuGAZxstFYgAVfz33cytR1seTD3ZabBSDd899
5 F8 w5 g+ A9 P* I/ n发现图片已经成功写入IPFS,如图:; t; J$ Y4 b+ Y: N+ \; | Z) p
# W( M" h3 V: F4 ]
; T$ u/ S% x% `# G4 v% g0 W4 a9 a
6 ?' {: t. V# a; ]6 [) p
" Z: Z+ |; {: h' E+ z$ w
运行结果37 a4 T0 c; F% e8 s3 I
2 B5 _% i% _& Y1 [, h1 h" b% _
备注:本地IPFS网关端口默认为8080,我的电脑上端口冲突了,系统自动修改为8082。
* s5 A1 `1 r* a8 k2 N. m搞定,收工。$ g r- ^' q" n& d* O
PS:刚入坑的小白,很多不懂,还请各位大佬多赐教,谢谢!
% I* ~6 T6 `5 M1 H7 ?3 f& s# V) d
% z! B! _% ]9 ^# _5 U- y
|
|