IPFS节点部署及连接java服务接口

news2024/11/16 23:31:30

文章目录

    • 引言
    • 前言:IPFS网络部署
        • 1.下载安装文件
        • 2.安装及初始化
        • 3.测试上传文件
    • 引入IPFS 依赖包
    • 初始化IPFS
    • 创建接口类以及实现类
    • 创建前端访问的控制类
    • 前端设计及验证

引言

该篇文章是记录使用IPFS存储文件与java的Springboot项目连接的过程,前端简单地用了一个vue的文件传输组件,将本地的文件上传到IPFS中存储,并返回哈希值。

前言:IPFS网络部署

1.下载安装文件

ipfs官网地址:https://dist.ipfs.tech/
下载kubo(go-ipfs),安装列表中适配的操作系统进行下载对应的安装文件。

2.安装及初始化
#1.解压安装包
$tar -zxvf kubo_v0.21.0_linux-amd64.tar.gz
#2.进入解压后的目录
$cd kubo
#3.执行install.sh脚本
$./install.sh
#4.执行初始化
$ipfs init
#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"]'
#6.启动ipfs
$ipfs daemon
#7.若启动时与本地服务端口发生冲突,可以在IPFS的配置中对端口进行重新指定
3.测试上传文件

在改目录下创建一个blockchain.txt文件,

在这里插入图片描述

ipfs 使用add 命令来添加内容到节点中, 在命令行输入:

$ipfs add blockchain.txt

在这里插入图片描述

当它文件添加到节点时,会为文件生成唯一的hash,可以使用ipfs cat 查看文件的内容:

$ipfs cat QmaXomPM2Kh1pNmhpvY1M5jFvThoZBHp2NckDJTbBnb6Xa

在这里插入图片描述

引入IPFS 依赖包

首先在创建的Springboot项目中的pom.xml文件中添加ipfs依赖,

<repositories>
		<repository>
			<id>jitpack.io</id>
			<url>https://jitpack.io</url>
		</repository>
</repositories>
<dependency>
		<groupId>com.github.ipfs</groupId>
		<artifactId>java-ipfs-http-client</artifactId>
		<version>v1.4.4</version>
</dependency>

在这里插入图片描述

初始化IPFS

初始化IPFS的过程主要是编写配置类,用于与本地你开启的IPFS节点进行连接,本篇文章只启动了一个IPFS节点,后续会进行多节点的连接。

首先配置IPFS系统的属性配置类IpfsProperties,需要注意的是multiAddr的设置,multiAddr的值用于指定IPFS节点的网络地址和端口,这样客户端就可以通过这个地址连接到IPFS节点。

当我们用ipfs daemon启动节点之后,就可以在控制台看到,

在这里插入图片描述

package com.example.eduction.utils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "ipfs.config")
public class IpfsProperties {
    private String multiAddr="/ip4/127.0.0.1/tcp/5001";
}

在这里插入图片描述

然后初始化相关类BeanConfig,

package com.example.eduction.utils;
import io.ipfs.api.IPFS;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import java.io.IOException;
/**
 * 初始化相关类
 */
@Log4j2
@Configuration
public class BeanConfig {
    @Resource
    private IpfsProperties ipfsProperties;
    @Bean
    public IPFS ipfs() throws IOException {
        IPFS ipfs = new IPFS(ipfsProperties.getMultiAddr());
        ipfs.refs.local();
        return ipfs;
    }
}

在这里插入图片描述

以上的两个类的代码我感觉可以用IPFS ipfs = new IPFS("/ip4/127.0.0.1/tcp/5001"),这一行代码搞定,但还没有验证,后续可以试试。

创建接口类以及实现类

首先创建接口类IpfsService,

package com.example.eduction.controller;
import com.example.eduction.utils.BeanConfig;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service
public interface IpfsService {

    String uploadToIpfs(String filePath) throws IOException;

    String uploadToIpfs(byte[] fileData) throws IOException;

    byte[] downFromIpfs(String hash);

    void downFromIpfs(String hash, String destFilePath);
}

在这里插入图片描述

然后创建实现类IpfsServiceImpl,

package com.example.eduction.controller;
import cn.hutool.core.io.FileUtil;
import io.ipfs.api.IPFS;
import io.ipfs.api.MerkleNode;
import io.ipfs.api.NamedStreamable;
import io.ipfs.multihash.Multihash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;


/**
 * 连接ipfs星际文件系统的文件上传和下载服务类
 */
@Service
public class IpfsServiceImpl implements IpfsService {

    @Autowired
    private IPFS ipfs;

    @Autowired
    public IpfsServiceImpl(IPFS ipfs){
        this.ipfs=ipfs;
    }
    /**
     * 指定文件路径上传文件到ipfs
     *
     * @param filePath 文件路径
     * @return 存储文件的寻址哈希
     * @throws IOException
     */
    @Override
    public String uploadToIpfs(String filePath) throws IOException {
        NamedStreamable.FileWrapper file = new NamedStreamable.FileWrapper(new File(filePath));
        MerkleNode addResult = ipfs.add(file).get(0);
        String hash = addResult.hash.toString();
        return hash;
    }
    /**
     * 将byte格式的数据,上传至ipfs
     *
     * @param fileData
     * @return 存储文件的寻址哈希
     * @throws IOException
     */
    @Override
    public String uploadToIpfs(byte[] fileData) throws IOException {
        NamedStreamable.ByteArrayWrapper file = new NamedStreamable.ByteArrayWrapper(fileData);
        MerkleNode addResult = ipfs.add(file).get(0);
        return addResult.hash.toString();
    }
    /**
     * 根据Hash值,从ipfs下载内容,返回byte数据格式
     * @param hash 文件寻址哈希
     * @return
     */
    @Override
    public byte[] downFromIpfs(String hash) {
        byte[] data = null;
        try {
            data = ipfs.cat(Multihash.fromBase58(hash));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

    /**
     * 根据Hash值,从ipfs下载内容,并写入指定文件destFilePath
     *
     * @param hash         文件寻址哈希
     * @param destFilePath 目标文件路径
     */
    @Override
    public void downFromIpfs(String hash, String destFilePath) {
        byte[] data = null;
        try {
            data = ipfs.cat(Multihash.fromBase58(hash));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (data != null && data.length > 0) {
            FileUtil.del(destFilePath);
            FileUtil.writeBytes(data, destFilePath);
        }
    }
}

在这里插入图片描述

创建前端访问的控制类

创建FileUploadController,我设置的调用路径为http://127.0.0.1:8423/upload , 这里文件上传接口编写需要注意的是文件的路径和名称,从前端上传的文件是以MultipartFile的形式传到后端的,然后我们利用getOriginalFilename()方法获取真实的文件名称,但这只是获取了文件的名称,而没有获取文件路径。这个文件路径是系统的绝对路径,因此我们要再加上dir前缀。

package com.example.eduction.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@CrossOrigin//支持跨域
public class FileUploadController {

    @Autowired
    IpfsServiceImpl ipfsService;
    @PostMapping("/upload")
    public String upload(MultipartFile file) throws Exception {
        System.out.println(file.getOriginalFilename());
        String originalfilename = file.getOriginalFilename();
        String dir="/fisco/Eduction/src/main/java/com/example/eduction/assets/";
        ipfsService.uploadToIpfs(dir+originalfilename);
        System.out.println(ipfsService.uploadToIpfs(dir+originalfilename));
        return ipfsService.uploadToIpfs(dir+originalfilename);
    }
}

在这里插入图片描述

前端设计及验证

前端采用vue+elementui,随便写了一个接口。

<template>
  <el-card class="box-card">
    <div slot="header" class="clearfix">
      <span>学历存证</span>
<!--      <el-button style="float: right; padding: 3px 0" type="text">操作按钮</el-button>-->
    </div>
    <div class="text item">
      {{'下载学历数据填写表'}}<el-button type="primary" style="margin-left: 100px;text-align: left" @click="downloadTable">点击下载</el-button>
    </div>
    <div class="text item">
      {{'上传填写好的学历数据填写表'}}

      <el-upload
        class="upload-demo"
        action="http://localhost:8463/upload"
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :on-success="uploadsuccess"
        :before-remove="beforeRemove"
        multiple
        :limit="3"
        :on-exceed="handleExceed"
        :file-list="fileList">
        <el-button type="primary" >点击上传</el-button>
        <div slot="tip" class="el-upload__tip">只能上传txt文件,且不超过500kb</div>
      </el-upload>
    </div>
    <el-button type="success" @click="confirmSubmit">确认提交</el-button>
  </el-card>
</template>

在这里插入图片描述

然后点击点击上传按钮,选择我自己的系统路径"/fisco/Eduction/src/main/java/com/example/eduction/assets/"下的文件,

成功上传之后就会显示出来,

在这里插入图片描述

并且,我在后端控制台设置了文件存储在IPFS后打印hash值,因此我们可以再后端看到hash值打印出来,说明我们上传成功。

在这里插入图片描述

最后我们验证一下,使用改hash索引是否能够在ipfs返回我们所存的文件内容,

在这里插入图片描述

结果返回我们存在filetest.txt文件里面的内容8623。

参考文章

IPFS 使用入门 | 登链社区 | 区块链技术社区 (learnblockchain.cn)

区块链 - 集成IPFS星际文件系统,并基于WeBASE-Front发送交易接口实现文件类上链存证的方案 - 个人文章 - SegmentFault 思否

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1788619.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

傲医医疗集成引擎 Rhapsody 在超融合信创平台表现如何?

作者&#xff1a;SmartX 商业团队 黄玉辉 随着越来越多的医疗用户基于超融合基础设施实现 IT 基础架构信创转型&#xff0c;超融合信创架构在医疗业务场景中的实际表现也得到更多关注。尤其是集成平台业务场景——作为三甲医院互联互通评级中不可缺少的核心业务系统&#xff0…

使用Ollama+OpenWebUI本地部署Gemma谷歌AI开放大模型完整指南

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;AI大模型部署与应用专栏&#xff1a;点击&#xff01; &#x1f916;Ollama部署LLM专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月4日10点50分 &#x1f004;️文章质量&#xff1…

Spring Boot既打jar包又打war包如何做

你好&#xff0c;我是柳岸花开。 引言 在软件开发中&#xff0c;根据不同的部署需求&#xff0c;我们可能需要将应用打包成不同的格式。Spring Boot作为目前流行的Java应用开发框架&#xff0c;提供了一种简单的方式来打包应用。本文将介绍如何利用Maven Profiles在Spring Boot…

Photoshop版本选择及系统要求

1、ps2018cc/2020cc版本 适合新手&#xff0c;增加了很多智能化操作&#xff0c;非常方便好上手。 2020&#xff1a; 2、ps2015版本 cc2015版本不论是功能还是硬件上&#xff0c;都是不二选择&#xff0c;适合于配置较低的电脑&#xff0c;该有的基本功能它都有。 3、2021/2…

【最新鸿蒙应用开发】——一篇搞懂什么是UIAbility

UIAbility组件 UIAbility组件是一种包含UI的应用组件&#xff0c;UIAbility组件是系统调度的基本单元&#xff08;最小单元&#xff09;&#xff0c;为应用提供绘制界面的窗口&#xff0c;主要用于和用户交互。一个应用可以包含一个或多个UIAbility组件。 UIAbility的设计理念…

PySpark特征工程(III)--特征选择

有这么一句话在业界广泛流传&#xff1a;数据和特征决定了机器学习的上限&#xff0c;而模型和算法只是逼近这个上限而已。由此可见&#xff0c;特征工程在机器学习中占有相当重要的地位。在实际应用当中&#xff0c;可以说特征工程是机器学习成功的关键。 特征工程是数据分析…

Windows下 CLion中,配置 OpenCV、LibTorch

首先按照win下C部署深度学习模型之clion配置pytorchopencv教程记录 步骤配置。 LibTorch 部分 在测试LibTorch时会出现类似 c10.dll not found 的问题&#xff08;Debug才有&#xff09;&#xff1a; 参考C部署Pytorch&#xff08;Libtorch&#xff09;出现问题、错误汇总和 …

git常见问题及解决

文章目录 git常见问题及解决1. 不同操作系统使用git时&#xff0c;CRLF的处理换行问题1.1 什么是CRLF和LF1.2 在Git中设置自动转换 2. 多个仓库相同代码推送被拒绝3. git使用vi编辑器时候报错&#xff1a;Swap file "./.git/.COMMIT_EDITMSG.swp" already exists!4. …

3. redis常见部署架构

redis常见部署架构 一、redis常见部署架构1、常见部署架构2、多实例部署2.1 规划安装目录、配置文件2.2.2 编辑实例配置文件2.2.3 启动实例2.2.4 测试数据读写 3、redis主从复制3.1 规划3.2 从服务器配置3.3 验证主从状态3.4 主从角色切换 4、分片集群4.1 原理4.2 分片集群的部…

completefuture造成的rpc重试事故

前言 最近经历了一个由于 completefuture 的使用&#xff0c;导致RPC重试机制触发而引起的重复写入异常的生产bug。复盘下来&#xff0c;并非是错误的使用了completefuture&#xff0c;而是一些开发时很难意识到的坑。 背景 用户反馈通过应用A使用ota批量升级设备时存在概率…

美容美发门店收银管理系统源码分享-美业系统App端闪退怎么办?

美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 活动促销 PC管理后台、手机APP、iPad APP、微信小程序 ▶ 手机App应用闪退怎么办&#xff1f;博弈美业系统为例 • 可能原因&#xff1a; 1、手机版本过低 2、未更新…

第二证券炒股技巧:短线炒股技巧?

在股票商场上&#xff0c;出资者分为长线和短线这两大类&#xff0c;其间短线炒股存在以下技巧&#xff1a; 1、早盘集合竞价时间上的技巧 早上集合竞价对短线出资者来说比较重要&#xff0c;其间早上集合竞价期间9&#xff1a;15-9:20之间出资者能够进行撤单操作&#xff0c…

Spring boot集成通义千问大模型实现智能问答

Spring boot集成通义千问大模型实现智能问答 背景 我在用idea进行java开发时发现了通义灵码这款免费的智能代码补全插件&#xff0c;用了一段时间了&#xff0c;感觉很不错。就想着在自己的项目中也能集成通义千问大模型实现智能回答&#xff0c;毕竟对接openai需要解决网络问…

【WEEK15】 【DAY1】异步任务【中文版】

2024.6.3 Monday 目录 17.异步、定时、邮件任务17.1.异步任务17.1.1.新建springboot-09-test项目17.1.2.创建一个service包17.1.2.1.创建一个类AsyncService 17.1.3.编写controller包17.1.3.1.编写AsyncController类 17.1.4.运行Springboot09TestApplication.java17.1.5.修改S…

Python课设-学生信息管理系统

一、效果展示图 二、前端代码 1、HTML代码 <1>index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

【Unity美术】spine软件的使用—2D动画的制作

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

通用代码生成器应用场景四,跨编程语言翻译

通用代码生成器应用场景四&#xff0c;跨编程语言翻译 如果您有一个Java工程&#xff0c;想把它移植到Rust或Golang语言中去&#xff0c;希望尽可能加快研发速度。 如果您的系统是通用代码生成器开发的&#xff0c;保留了系统的SGS源文件或者SGS2的Excel模板&#xff0c;您可…

Flink的简单学习(kafka)三

一 Kafka的介绍 1.kafka是一个高吞吐的分布式消息系统&#xff0c;是一个消息队列。 2.生产者负责生产数据 &#xff0c;消费者负责消费数据 3.特点&#xff1a; 生存者消费者模型&#xff0c;FIFO 高性能&#xff1a;单节点支持上千个客户端&#xff0c;百MB/s吞吐 持久…

Pycharm创建Conda虚拟环境时显示CondaHTTPErOT

原因&#xff1a;conda源出问题了&#xff0c;之前可以用&#xff0c;现在报错。 最好的解决方案&#xff1a;找到conda源&#xff0c;换源即可。 步骤&#xff1a; 1.修改 .condarc 文件&#xff08;文件的位置在&#xff1a;C:\Users\(你的用户名)\.condarc&#xff09;&a…

关于认证协议

本地用户认证 本地认证的意思就是&#xff0c;我们的电脑上存储着自己的账号密码&#xff0c;无论电脑是否联网&#xff0c;只要能开机&#xff0c;就可以输入账号密码登录到电脑中&#xff0c;工作组就是采用本地认证 本地认证流程 winlogon.exe -> 接收用户输入 -> …