ipfs使用

1.mac安装ipfs——使用npm工具

sudo npm install ipfs --global

2.本地上传文件并同步网络

  1. touch index.html

  2. vim index.html

  3. 初始化过程,生成本地节点

ipfs init

  1. 保存在本地ipfs

ipfs add index.html

image-20190926182126347
  1. 同步到网络中

ipfs daemon

注意链接的格式:https://ipfs.io/ipfs/QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o

image-20190926182439500

image-20190926182419163

3.ipfs项目

  1. ipfs-desktop

https://github.com/ipfs-shipyard/ipfs-desktop

image-20190926182825385

4. ipfs后台界面

localhost:5001/webui

image-20190926183100234 image-20190926183156292

5.与浏览器交互

  1. npm install -g create-react-app

  2. create-react-app ipfs-demo

  3. 进入ipfs-demo文件夹,安装ipfsjs模块

    npm install ipfs-api --save

    ipfs-api改名字了,改成ipfs-http-client

    会发现package.json文件依赖会多出ipfs-api

image-20190926200206212
  1. 解决跨域,端口不一致问题
1
2
3
4
5
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"]'

使用ipfs config show就会看到config配置多出了API配置:

image-20190926200649544

  1. 运行react项目

    npm start

  2. 修改App.js文件内容——(react必学)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    import React, { Component } from 'react';
    import './App.css';

    class App extends Component {

    constructor(props) {
    super(props);
    this.state = {
    strHash: null,
    strContent: null
    }
    }

    render() {
    return (
    <div className="App">
    <input
    ref="ipfsContent"
    />
    <button onClick={() => {
    let ipfsContent = this.refs.ipfsContent.value;
    console.log(ipfsContent);
    }}>提交到IPFS</button>

    <p>{this.state.strHash}</p>

    <button onClick={() => {
    console.log('从ipfs读取数据。')
    }}>读取数据</button>
    <h1>{this.state.strContent}</h1>
    </div>
    );
    }
    }

    export default App;

    当我们在输入框中输入一个字符串时,点击提交到IPFS按钮,将文本框中的内容取出来打印,之后我们将这个数据上传到IPFS。点击读取数据按钮,我们也只是随便打印了一个字符串,后面需要从IPFS读取数据,然后将读取的数据存储到状态机变量strContent中并且展示出来。

  3. 导入ipfs模块并使用

    1
    2
    const ipfsAPI = require('ipfs-api');
    const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'});
  4. 编写上传大文本字符串到IPFS的Promise函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    saveTextBlobOnIpfs = (blob) => {
    return new Promise(function(resolve, reject) {
    const descBuffer = Buffer.from(blob, 'utf-8');
    ipfs.add(descBuffer).then((response) => {
    console.log(response)
    resolve(response[0].hash);
    }).catch((err) => {
    console.error(err)
    reject(err);
    })
    })
    }

    response[0].hash返回的是数据上传到IPFS后返回的HASH字符串。

  5. 上传数据到IPFS

    1
    2
    3
    4
    this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {
    console.log(hash);
    this.setState({strHash: hash});
    });

    ipfsContent是从文本框中取到的数据,调用this.saveTextBlobOnIpfs方法将数据上传后,会返回字符串hash,并且将hash存储到状态机变量strHash中。

  6. 提交数据的完整代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    import React, {Component} from 'react';
    import './App.css';

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

    class App extends Component {

    constructor(props) {
    super(props);
    this.state = {
    strHash: null,
    strContent: null
    }
    }

    saveTextBlobOnIpfs = (blob) => {
    return new Promise(function(resolve, reject) {
    const descBuffer = Buffer.from(blob, 'utf-8');
    ipfs.add(descBuffer).then((response) => {
    console.log(response)
    resolve(response[0].hash);
    }).catch((err) => {
    console.error(err)
    reject(err);
    })
    })
    }

    render() {
    return (<div className="App">
    <input ref="ipfsContent" />
    <button onClick={() => {
    let ipfsContent = this.refs.ipfsContent.value;
    console.log(ipfsContent);
    this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {
    console.log(hash);
    this.setState({strHash: hash});
    });
    }}>提交到IPFS</button>

    <p>{this.state.strHash}</p>

    <button onClick={() => {
    console.log('从ipfs读取数据。')
    }}>读取数据</button>
    <h1>{this.state.strContent}</h1>
    </div>);
    }
    }

    export default App;
  7. 刷新网页看后台数据

  8. 从ipfs读取数据

1
2
3
4
5
6
ipfs.cat(this.state.strHash).then((stream) => {
console.log(stream);
let strContent = Utf8ArrayToStr(stream);
console.log(strContent);
this.setState({strContent: strContent});
});

streamUint8Array类型的数据,下面的方法是将Uint8Array转换为string字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function Utf8ArrayToStr(array) {
var out, i, len, c;
var char2, char3;

out = "";
len = array.length;
i = 0;
while(i < len) {
c = array[i++];
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
default:
break;
}
}

return out;
}
  1. 完整源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import React, {Component} from 'react';
import './App.css';

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

function Utf8ArrayToStr(array) {
var out,
I,
len,
c;
var char2,
char3;

out = "";
len = array.length;
i = 0;
while (i < len) {
c = array[i++];
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
break;
default:
break;
}
}

return out;
}

class App extends Component {

constructor(props) {
super(props);
this.state = {
strHash: null,
strContent: null
}
}

saveTextBlobOnIpfs = (blob) => {
return new Promise(function(resolve, reject) {
const descBuffer = Buffer.from(blob, 'utf-8');
ipfs.add(descBuffer).then((response) => {
console.log(response)
resolve(response[0].hash);
}).catch((err) => {
console.error(err)
reject(err);
})
})
}

render() {
return (<div className="App">
<input ref="ipfsContent" />
<button onClick={() => {
let ipfsContent = this.refs.ipfsContent.value;
console.log(ipfsContent);
this.saveTextBlobOnIpfs(ipfsContent).then((hash) => {
console.log(hash);
this.setState({strHash: hash});
});
}}>提交到IPFS</button>

<p>{this.state.strHash}</p>

<button onClick={() => {
console.log('从ipfs读取数据。')
ipfs.cat(this.state.strHash).then((stream) => {
console.log(stream);
let strContent = Utf8ArrayToStr(stream);
console.log(strContent);
this.setState({strContent: strContent});
});
}}>读取数据</button>
<h1>{this.state.strContent}</h1>
</div>);
}
}

export default App;
  1. 预览结果

image-20190926203811361

Contents
  1. 1. 1.mac安装ipfs——使用npm工具
  2. 2. 2.本地上传文件并同步网络
  3. 3. 3.ipfs项目
  4. 4. 4. ipfs后台界面
  5. 5. 5.与浏览器交互