基于IPFS去中心化相册以太坊Dapp
Dapp-IPFS-Image
基于IPFS去中心化相册以太坊Dapp
注意: 使用该 github 克隆到本地, 需要 执行 $ npm install 安装依赖 node_modules
安装IPFS
官网(访问不了时,需要科学上网) https://ipfs.io
下载 解压缩
$ tar xvfz go-ipfs_v0.4.10_darwin-amd64.tar.gz
$ cd go-ipfs
$ mv ipfs /usr/local/bin/ipfs
创建IPFS节点
$ ipfs init
$ cd ~/.ipfs
启动服务器
ipfs daemon
跨域资源共享 CORS配置
control + c 终止ipfs服务器进程
$ 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服务器
$ ipfs daemon
新建终端执行:
$ ipfs cat /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme
打开http://localhost:5001/webui会看到UI界面
需要 truffle ,node.js ,npm ,react 环境安装 参考之前环境配置文章
项目开发
新建项目文件夹
$ mkdir 项目名IPFS-Image
cd IPFS-Image
下载unbox react 框架
$ truffle unbox react
安装ipfs-api
$ npm install ipfs-api --save-dev
验证框架和环境:
编译合约
$ truffle compile
开启前端
$ npm start
看见 项目页面, ok
修改项目框架代码:
Atom编辑器打开项目:
$ atom ./
编写智能合约
修改contracts/SimpleStorage.sol文件
pragma solidity ^0.4.19;
contract SimpleStorage {
string[] public photoArr; //定义一个 装图片hash值的字符串数组function storePhoto(string hash) public { //定义添加新图片hash方法photoArr.push(hash); //往字符串数组末尾 添加 新图片的 hash
}function getPhoto(uint index) public view returns (uint, string){ //定义函数:传入图片序列号,获取图片hash数组长度 和 对应序列号的 装图片hash值的字符串数组return (photoArr.length, photoArr[index]);
}
}
修改 src/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’
import ipfsAPI from ‘ipfs-api’
const ipfs = ipfsAPI({host: ‘localhost’, port: ‘5001’, protocal: ‘http’})
const contractAddress = “0xd7d25cd0f1ab028a43576b93380c52992716a0d1”
let simpleStorageInstance
let saveImageOnIpfs = (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 = {photos: [],count: 0,web3: null}
}componentWillMount() {
// Get network provider and web3 instance. See utils/getWeb3 for more info.getWeb3.then(results => {this.setState({web3: results.web3})this.instantiateContract()}).catch(() => {console.log('Error finding web3.')})
}instantiateContract() {const that = thisconst contract = require('truffle-contract')const simpleStorage = contract(SimpleStorageContract)simpleStorage.setProvider(this.state.web3.currentProvider)this.state.web3.eth.getAccounts((error, accounts) => {simpleStorage.at(contractAddress).then((instance) => {simpleStorageInstance = instance}).then(result => {return simpleStorageInstance.getPhoto(0)}).then(result => {console.log(result)let imgNum = result[0].c[0]if(imgNum===0){return}if(imgNum===1){this.setState({count: imgNum,photos: this.state.photos.concat([result[1]])})}if(imgNum>1){for(let i=0;i<imgNum;i++){(function(i){simpleStorageInstance.getPhoto(i).then(result => {that.setState({photos: that.state.photos.concat([result[1]])})})})(i)} }})})
}render() {let doms = [],photos = this.state.photosfor(let i=0; i<photos.length;i++){doms.push(<div key={i}><img src={"http://localhost:8080/ipfs/" + photos[i]}/></div>)}return (<div className="App"><header>上传图片至ipfs,并保存信息至以太坊区块</header><div className="upload-container"><label id="file">选择图片</label><input type="file" ref="file" id="file" name="file" multiple="multiple" onChange={e => this.change(e)}/><button onClick={() => this.upload()}>上传</button></div><div className="img-container">{doms}</div></div>);
}upload() {var file = this.refs.file.files[0];console.log(file)var reader = new FileReader();// reader.readAsDataURL(file);reader.readAsArrayBuffer(file)reader.onloadend = (e) => {//console.log(reader);saveImageOnIpfs(reader).then((hash) => {console.log(hash);this.setState({imgSrc: hash})simpleStorageInstance.storePhoto(hash, {from: this.state.web3.eth.accounts[0]}).then(() => {console.log("写入区块成功")this.setState({photos: this.state.photos.concat([hash])})})});}
}
change(e){console.log(e.target.value)
}
}
export default App
修改src/app.css 前端 UI CSS
/* PAGE */
- {
margin: 0;
padding: 0;
}
html, body, #root, .App{
width: 100%;
height: 100%;
}
.App{
display: flex;
flex-direction: column;
}
header{
height: 60px;
line-height: 60px;
padding: 0 20px;
background: #cfd8dc;
border-bottom: 1px solid #eee;
font-size: 24px;
color: #fff;
}
.upload-container {
height: 100px;
display: flex;
justify-content: center;
align-items: center;
background: #cfd8dc;
color: #666;
}
.img-container {
flex: 1;
display: flex;
flex-wrap: wrap;
justify-content: center;
/* align-items: center; */
height: 80px;
background: #eceff1;
}
.img-container div{
width: 200px;
height: 200px;
margin: 20px;
box-shadow: 0 0 10px #ccc;
border-radius: 3px;
}
.img-container div{
display: flex;
justify-content: center;
align-items: center;
}
.img-container div img{
max-width: 200px;
max-height: 200px;
}
.upload-container input{
font-size: 14px;
display: flex;
align-items: center;
margin-left: 10px;
}
.upload-container button{
height: 30px;
width: 80px;
line-height: 30px;
font-size: 14px;
color: #fff;
border: 0;
outline: none;
cursor: pointer;
border-radius: 3px;
background: cadetblue
}
.upload-container button:hover{
opacity: 0.7;
}
本地测试:
编译部署合约
$ truffle develop //启动truffle本地合约测试框架
(Mnemonic:后面 就是本地 以太坊测试框架区块链 钱包的助记词,可用于直接导入 Metamask钱包中)
$ truffle(develop)> compile //编译
$ truffle(develop)> migrate //部署合约
复制智能合约 SimpleStorage 的地址
修改 src/app.js 合约地址
const contractAddress = “0x345ca3e014aaf5dca488057592ee47305d9b3e10” //SimpleStorage合约地址
新建终端(truffle develop框架不要关), 启动IPFS服务器:
$ ipfs daemon
新建终端, 启动 前端:
$ npm start
安装 Metamask 钱包(科学上网):
https://metamask.io
设置RPC
添加http://localhost:9545
调到RPC localhost 9545网络
导入 truffl 框架 分配的私钥
选择图片文件上传. 提示消耗Gas 点击SUBMIT
如果消耗gas出错, 可以导入truffle 助记词到MetaMask钱包,重试.
图片显示项目成功
可以多上传几张测试
基于IPFS去中心化相册以太坊Dapp相关推荐
- 3步! 老司机教你如何在以太坊上构建基于Token去中心化投票系统!
作者 | Doug Crescenzi 译者 | 王柯凝 出品 | CSDN.区块链大本营 如果想在以太坊平台上构建一个去中心化的自治系统,其实有很多种不同的方法可供你选择.其中,最常用的方法之一就是 ...
- python去中心化_EOS区块链dApp去中心化应用汇总
EOS最近一直在区块链新闻中.它的主干网(公有链)发布了,人们仍然对它们持怀疑态度.在101Blockchain.com网站上,我们知道会有紧张的投资者.怀疑的分析家和像你一样好奇的读者.这就是为什么 ...
- 区块链发展第三阶段:去中心化金融
2017年12月17日,以太坊上第一个完全去中心化的数字稳定币--Dai正式发布,它是去中心化金融(DeFi)的基石.DeFi的最终目的是构建一个透明的金融系统,这个金融系统向任何可以连接互联网的人开 ...
- Web3.0介绍与产业赛道(去中心化,金融与数字资产,应用与存储,区块链技术)
文章目录 1.web3.0时代--区块链技术 2.产业赛道:去中心化金融与数字资产 3.产业赛道:去中心化应用与存储 4.区块链:基础设施与区块链安全和隐私 1.web3.0时代--区块链技术 Web ...
- 去中心化的区块链如何理解?
这里要讲重点了,即区块链的去中心化到底什么样?它又是如何保证交易的可信性和准确性的呢? 去中心化最初的来源,是一个自然科学中的生态学原理.在一个分布有众多节点的系统中,每个节点各司其职互不干扰,具有高 ...
- 继FCoin后的下一轮浪潮 —— 去中心化交易所的逆风翻盘
本文由微信公众号DappVision原创首发,转载请联系授权 互联网时代的腥风血雨是在烧钱补贴中结束的,从2011年的千团大战,到17年的ofo与摩拜之争,基本都是这个套路. 而在区块链的时代,FCo ...
- 元宇宙产业委联席秘书长叶毓睿:去中心化和去中介化的定义、区别,以及和元宇宙的关系
原创 Peter Ye 转自:乐生活与爱IT Plus 近日有个有关元宇宙的线上分享,有位名叫谢晓雪的听众提了一个我之前没思考过的问题:去中心化和去中介化的区别? 当时我回答了一部分,但主要是讲的之 ...
- 论述《区块链智能合约的合同效力认定》去中心化金融的钞能力赛道
| 没有喧嚣,没有问候的"沉默",请安静听完这段征途故事! 摘要 智能合约是自动执行合同条款的代码协议,其以代码替代传统人为执行合同,本质上是运用代码"编译"传 ...
- 去中心化云存储的前世今生 | 存储技术分享活动回顾
由 Oneblock+.Parity 联合主办的"Substrate Saturday" 线上直播系列活动第九期在3月 26 日顺利举办,线上直播观看次数近 600 次,互动评论约 ...
最新文章
- iOS架构设计-URL缓存(下)
- 【算法导论】插入排序
- c语言和画图软件,大佬们,小菜鸟想问一问用vc编译器做简易画图软件
- Python编程系列教程第16讲——拷贝自身到系统目录
- 赠书:京东当当新书榜TOP1的“算法小抄”!
- python类修饰器_《Python有什么好学的》之修饰器
- 点击按钮测试用例标题_怎么写测试用例?
- maven 上传jar 包含源码
- 友盟分享快速集成--学习记录
- 【slighttpd】基于lighttpd架构的Server项目实战(8)—状态机机制回顾
- 微信支付v2开发(7) 告警通知
- 兄弟连教育分享:用CSS实现鼠标悬停提示的方法
- 【基本办公软件】万彩办公大师教程丨彩色转化PDF为黑白PDF
- Apache DolphinScheduler 3.0.0 正式版发布!
- 用Notepad++实现文本比较
- 使用EKL(Elasticsearch、Kibana、Logstash)进行服务器日志的汇聚与监控
- NVL和NVL2有什么区别,NULLIF 的使用.
- 腾讯企业 html邮件模板,腾讯企业邮箱DMARC设置指南(TXT记录)
- android声音录制音量太小,为什么总是感觉手机音量太小?跟我这样设置,声音瞬间大上许多...
- 指向数组元素的指针和指针数组
热门文章
- python伪造邮件发件地址_Python3学习系列(四):编写属于自己的邮件伪造工具...
- mysql:增删改查语句大全
- tcl基本语法:中括号[ ]、大括号{ }、双引号“ ”
- 新的天花?高通量如何加速抗猴痘病毒化合物筛选 | MedChemExpress
- 802.11 wireless 详解
- 一文了解深度学习实战——预测篇
- 时间复杂度的计算详解
- 《C++ Primer》第5章 5.2节习题答案
- strchr()函数与strrchr()函数的实现
- WE WANT U ┃中天微 国防科技大学2017届硕士专场校园宣讲会