您的位置:首页 > Web前端 > React

使用React前端框架结合js-ipfs-api实现IPFS的文本数据流传输

2018-02-26 18:26 1126 查看
本文我们将通过React这个js前端框架来实现一个简易的页面,通过官方提供的js-ipfs-api,我们可以在页面的文本框中输入任意文本,然后提交上传到IPFS节点网络中,再利用hash参数把上传的文本数据显示出来。

React简介及安装

React是由Facebook和Instagram来开发的一种用来创建用户界面的JavaScript库。

React的简单入门见https://reactjs.org/tutorial/tutorial.html

首先你要保证电脑上已经安装了Node.js的最近版本,然后可以根据安装教程来创建新项目。

npm install -g create-react-app


sily@lyg-sily:~$ npm install -g create-react-app
/home/sily/.nvm/nvm/versions/node/v9.3.0/bin/create-react-app -> /home/sily/.nvm/nvm/versions/node/v9.3.0/lib/node_modules/create-react-app/index.js
+ create-react-app@1.5.2
added 114 packages in 26.067s
sily@lyg-sily:~$ create-react-app --version
1.5.2


React项目创建

sily@lyg-sily:~$ create-react-app ipfs-demo

Creating a new React app in /home/sily/ipfs-demo.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...

> uglifyjs-webpack-plugin@0.4.6 postinstall /home/sily/ipfs-demo/node_modules/uglifyjs-webpack-plugin
> node lib/post_install.js

+ react-scripts@1.1.1
+ react@16.2.0
+ react-dom@16.2.0
added 1155 packages in 131.72s

Success! Created ipfs-demo at /home/sily/ipfs-demo
Inside that directory, you can run several commands:

npm start
Starts the development server.

npm run build
Bundles the app into static files for production.

npm test
Starts the test runner.

npm run eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

cd ipfs-demo
npm start

Happy hacking!


在项目根目录输入
npm start
命令,查看项目在浏览器的显示效果:



安装js-ipfs-api

npm install --save ipfs-api


安装成功会在项目node_modules目录下多出ipfs-api文件夹,在package.json下增加依赖包信息:



添加UI逻辑

修改
src/App.js
里面的代码,主要是
render()
中的页面布局:

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"
style=/>
<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
中并展示出来。

导入IPFS

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


编写上传大文本字符串到IPFS的Promise函数

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
字符串。

上传数据到IPFS

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


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

跨域资源共享CORS配置

跨域资源共享
(CORS)
配置,依次在终端执行以下代码:

$ 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"]'


用正确的端口运行
daemon


$ ipfs config Addresses.API
/ip4/127.0.0.1/tcp/5001
$ ipfs config Addresses.API /ip4/127.0.0.1/tcp/5001
$ ipfs daemon


从IPFS读取数据

ipfs.cat(this.state.strHash).then((stream) => {
console.log(stream);
let strContent = Utf8ArrayToStr(stream);
console.log(strContent);
this.setState({strContent: strContent});
});


编写
Utf8ArrayToStr()
方法将
Uint8Array
类型的
stream
变量转换成
string
字符串:

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;
}


最终完整的
App.js
代码如下:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

const ipfsAPI = require('ipfs-api');
const ipfs = ipfsAPI({host:'localhost', port:'5001', protocal:'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"
style={{width:200,height:30}}/>
<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>
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}

export default App;


运行效果测试



参考

https://reactjs.org/tutorial/tutorial.html

https://github.com/ipfs/js-ipfs-api/blob/master/README.md

http://www.liyuechun.org/2017/11/22/ipfs-api/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  IPFS 区块链
相关文章推荐