lemooljiang avatar

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

lemooljiang

Published: 23 Oct 2021 › Updated: 23 Oct 2021

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

说明

用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"  //改大点


ipfsapigateway访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的托管,也算是个很实用的功能,小伙伴们可以用起来哦!

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

Written by

Designer , Poet , Technology enthusiasts

Read more #smartcontract posts


Best Posts From lemooljiang

We have not curated any of lemooljiang's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From lemooljiang