IPFS使用指南(更新版) / 学习智能合约#53

Words
581
Reading
3 min
Listen
Play
5y

说明

用IPFS提供web服务,需要有两部分,一是服务器端开启daemon, 二是前端用js来访问服务器。这与一般的网站服务是一样的。所以,在此我分为服务器端和前端两部分来实现IPFS的服务。

简介

IPFS的全称是InterPlanetary File System(星际文件系统),从名称上看,这是一个很炫酷、很有野心的项目。简单地说它就是一个点对点的分布式文件系统。官网和github都可以找到所有的相关资料。建议从它的白皮书,和直译中文版本开始了解,后面我们会慢慢地认识它。白皮书上指出了多个应用场景。

下载与资源

官网 |
手册 |
github手册 |
戴嘉乐博客 |
js |
ipfs-core |
ipfs-http-client |
前端操作文件

IPFS的公共网关

IPFS的公共网关还是蛮稀缺的,而且很多在国内是访问不了的,所以,只能多试下啰。

查询公共网关

https://cloudflare-ipfs.com/ipfs/
https://crustwebsites.net
https://ipfs.io/ipfs
https://ipfs.jeroendeneef.com/ipfs
https://na.siderus.io/ipfs/
https://ipfs.busy.org/ipfs
http://gateway.ipfs.io/ipfs
https://siderus.io/ipfs/
https://ipfs.jes.xxx/ipfs/

一、服务器端(用go版)

安装

mkdir /home/ipfs
cd /home/ipfs
wget https://github.com/ipfs/go-ipfs/releases/download/v0.10.0/go-ipfs_v0.10.0_linux-amd64.tar.gz

tar -zxvf go-ipfs_v0.10.0_linux-amd64.tar.gz
cd go-ipfs
./install.sh
  //Moved ./ipfs to /usr/local/bin

ipfs version  //ipfs version 0.10.0
ipfs --help  

//初始化,/root/.ipfs
ipfs init

ipfs id     //自己的id
ipfs daemon //开启进程
  Swarm announcing /ip6/::1/tcp/4001
  Swarm announcing /ip6/::1/udp/4001/quic
  API server listening on /ip4/0.0.0.0/tcp/9000
  WebUI: http://0.0.0.0:9000/webui
  Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080
  Daemon is ready

查看配置config

cd /root/.ipfs
cat config

设置端口和跨域

js版无法跨域,不要用,用go版

//需要改动的地方
"Addresses": 
    "StorageMax": "100GB"  //改大点


ipfs的api和gateway默认访问路径为127.0.0.1.如需要其他机器访问,需要修改
ipfs config Addresses.Gateway /ip4/0.0.0.0/tcp/8080  //访问接口 跨域
ipfs config Addresses.API /ip4/0.0.0.0/tcp/9000    //上传接口

//http corps问题 在控制台粘入以下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"]'

systemctl-service

用systemctl管理ipfs的进程和重启等事务

which命令
  which ipfs
查看ipfs执行文件的位置:
  /usr/local/bin/ipfs

//创建文件
vim /lib/systemd/system/ipfs.service

//粘入代码
[Unit]
Description=IPFS Daemon Client
[Service]
ExecStart=/usr/local/bin/ipfs daemon
Restart=always
RestartSec=30
Type=simple
User=root
Group=root
[Install]
WantedBy=multi-user.target

//命令
systemctl daemon-reload
systemctl enable ipfs
开启服务: systemctl start ipfs
关闭服务: systemctl stop ipfs
查看状态: systemctl status ipfs  //q退出
查看进程:ps -aux | grep ipfs

nginx配置反向代理

IPFS是不提供https服务的,所以,必须使用nginx的反向代理提供https!

前提:nginx的https已由Certbot配置好了,再加上以下代码即可。

server {
    server_name example.com;    
    location / {
        proxy_pass http://127.0.0.1:8080;       
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    listen 8081 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    listen [::]:9001 ssl ipv6only=on; # managed by Certbot
    listen 9001 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    server_name  example.com;
    location / {
        proxy_pass http://127.0.0.1:9000;
     }
}

二、前端(ipfs-http-client)

安装和配置

npm install ipfs-http-client --save  //53.0.1

//main.js
import {create} from 'ipfs-http-client'
const ipfs = create({ host: 'example.com', port: '9000', protocol: 'https' })

Vue.prototype.ipfs = ipfs  //挂载到全局

上传文本到ipfs

//上传文本
const content = Buffer.from('hello lemool,hihihi!!')
let res = await that.ipfs.add(content)
console.log(345, res.path) 

//获取并解析文本
let hash = "QmPbYFA1uFXoi7Gfodxebq1Fxaj9oNU8tnSHZSzdbUGhn4"
for await (const chunk of ipfs.cat(hash)) {
  console.log(66, chunk)
  console.log(68, utf8ArrayToStr(chunk))
}

Utf8ArrayToStr

将UTF-8字符转成字符串

utf8ArrayToStr(array) {
  let out, i, len, c
  let 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
      }
  }
  return out
},

上传图片到ipfs

<b-form-file placeholder="上传封面图(建议尺寸:400*300像素)" 
    browse-text="文件" v-model="file" 
    class="title" accept=".jpg, .jpeg, .png, .webp, .gif" >
</b-form-file>

readFile(file){
  this.isLoadingFile = true
  return new Promise(resolve => {
    let reader = new FileReader()
    reader.readAsArrayBuffer(file)
    reader.onload = (event) => {
      resolve(Buffer.from(event.target.result))
    }
  })
},
async upImage(file){
  let content = await this.readFile(file)
  let res = await this.ipfs.add(content)
  this.imgHash = res.path
  console.log(88, res)
},

上传视频到ipfs

和上传图片是一个函数,几乎一样。

<b-form-file placeholder="上传mp4视频" browse-text="文件" v-model="file" class="mb-2" accept=".mp4" ></b-form-file>

//上传视频
readFile(file){
  this.isLoadingFile = true
  return new Promise(resolve => {
    let reader = new FileReader()
    reader.readAsArrayBuffer(file)
    reader.onload = (event) => {
      resolve(Buffer.from(event.target.result))
    }
  })
},
async upImage(file){
  let content = await this.readFile(file)
  let res = await this.ipfs.add(content)
  this.imgHash = res.path
  console.log(88, res)
},

videostream播放视频

cnpm install videostream --save

<video ref="myvideo" controls autoplay="autoplay" width="90%" ></video>

import VideoStream from 'videostream'
Play(hash){
  //得到视频hash播放
  let that = this
  let stream
  new VideoStream({
    createReadStream: function createReadStream (opts) {
      const start = opts.start
      const end = opts.end ? start + opts.end + 1 : undefined
      // If we've streamed before, clean up the existing stream
      if (stream && stream.destroy) {
        stream.destroy()
      }
      // This stream will contain the requested bytes
      stream = that.ipfs.catReadableStream(hash,  {
        offset: start,
        length: end && end - start})
      stream.on('error', (error) => console.log(error))
      return stream
    }
  }, that.$refs.myvideo)
},

现在IPFS常用于NFT的托管,也算是个很实用的功能,小伙伴们可以用起来哦!

IPFS使用指南(更新版) / 学习智能合约#53 | Ecency