kkfileview与minio整合实现文件上传与预览

1.概叙

  • kkfileview 比较火热的在线预览工具,gitee stat10K+。点击这里跳转kkfileview官网。
  • minio 是apache开源的高性能、分布式的对象存储系统,点击这里跳转minio官网。
  • 本文将介绍整合minio与kkfileview部署流程与详细代码。

2.功能与特性

  • kkfileview
    功能:文档图片在线预览
    特性:
    1. springboot搭建,方便二开,部署简便
    2. 支持多种文件格式,如doc,docx,Excel,pdf,txt,zip,rar,图片等等,内部集成openOffice、libreOffice
    3. 使用预览缓存,提升预览效率。默认RocksDB
    4. 支持FTP源
  • minio
    功能:存储服务
    特性:
    1. 轻量:支持多种方式部署docker、k8s、win、mac等
    2. 高性能:可以100%的运行在标准硬件,在标准硬件条件下它能达到55GB/s的读、35GG/s的写速率。
    3. 兼容Amazon S3:可以使用Minio SDK,Minio Client,AWS SDK和AWS CLI访问Minio服务器。
    4. 安全性:纠删码(擦除码)Minio使用按对象的嵌入式擦除编码保护数据。MinIO uses Reed-Solomon code to shard objects into variable data and parity blocks. For example, in a 12 drive setup, an object can be sharded to a variable number of data and parity blocks across all the drives - ranging from six data and six parity blocks to ten data and two parity blocks.(官网原话,大致意思就是说即便丢失1/2的磁盘也能找回数据)。纠删码根据矩阵原理实现数据的校验与恢复,有兴趣的可点击这里
    5. 一致性:集群部署合单机下,所有读写操作都严格遵守read-after-write一致性模型。

3.安装部署

3.1 kkfileview
3.1.1 环境依赖
jdk 8
maven 3
3.1.2 下载安装
  1. kkfileview下载地址
  2. 导入idea。
  3. 源码分析
  • 主要分析在线预览接口(/onlinePreview)
    /onlinePreview
  • 通过文件属性去工厂中获取对应的实现类(此处主要使用工厂模式+策略模式+枚举),具体就就不一一分析了,看看常用office文档如何实现预览的吧。
    缓存
  • 这里判断了下缓存中是否存在,不过有意思的是这里缓存继续使用了策略模式,源码提供了三种缓存方式(redis、rocksDB、JDK内置map)默认使用rocksDB。
  • 接着往下 DownloadUtils.downLoad 方法,具体就不图片展示了,后面还有很多内容,大致说一下windows 环境下就是在你项目路径下创建一个file文件夹(Linux在/opt/kkFileView-**/file,别问我为啥知道,看看ConfigUtils.getHomePath,再看看DockerFile ENV环境变量),并把上传的url文件copy到创建的文件夹下。
  • OK,原始图片下载了,继续开工,先生成PDF存入到本地再说。
    officeToPdfService.openOfficeToPDF(filePath, outFilePath);
    
  • 成功后加入缓存,不过这里好像写的有点BUG,如果是存在同名文件,而内容不相同,缓存中还是只存一个,所以文件名需要唯一处理的,可以计算文件的MD5,然后作为文件名,因为我们使用了minio所以继续往下,我们试着用minio去解决这个小问题。
    fileHandlerService.addConvertedFile(pdfName, fileHandlerService.getRelativePath(outFilePath));
    
3.1.3 minio-client搭建
  1. 新建minio-client模块,大致结构如下图,源码大多参考官网SDK,需要注意的就是文件名设置唯一,图中划线处(雪花算法生成ID看这里
    项目结构
  2. 导入minio客户端依赖
		<dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.1</version>
        </dependency>
  1. 新建DockerFile文件并写入
FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER YangYu
ADD target/minio-4.0.0.jar /opt/app.jar
EXPOSE 20500
ENTRYPOINT ["java", "-jar", "/opt/app.jar","-Dfile.encoding=UTF-8"]
  1. 打包并制作成镜像,推送到远程仓库。这里就不详细说明制作镜像过程了,也比较简单,看下最终镜像结果如图:
    这两个镜像kkfileview 与 minio 客户端就搭建好了,下面开始搭建部署minio服务与部署kkfileview、minio-client
3.2 minio服务搭建(集群版)与整合
3.2.1环境依赖
centos 7
docker 20.10.10
docker-compose 1.27.2
3.2.2 安装部署
  1. 新建minio-kkfileview文件夹
mkdir minio-kkfileview
  1. 编写docker-compose-private.yaml
vim docker-compose-private.yaml

类容如下:

version: '3.7'

services:

    kkfileview-service:
        image: registry.cn-hangzhou.aliyuncs.com/vote_2020/kkfileview:1.0.0 # 远程仓库镜像名:版本
        container_name: kkfileview-service # 容器名
        restart: always #docker重启跟着启动
        ports: #映射端口
            - "8012:8012"
            - "9999:9999"
        networks: #网络模式
            - net
    minio-client:
        image: registry.cn-hangzhou.aliyuncs.com/vote_2020/minio:1.0.0
        container_name: minio-client
        restart: always
        ports:
            - "20500:20500"
        networks:
            - net


networks:
  net:
    driver: bridge

  1. 编写docker-compose-public.yaml (官方yaml看 这里 自备梯子)
vim docker-compose-public.yaml

类容如下:

version: '3.7'

# Settings and configurations that are common for all containers
# 每个节点设置两块磁盘
x-minio-common: &minio-common
  image: minio/minio
  command: server --console-address ":9001" http://minio{1...3}/data{1...2}
  expose:
    - "9000"
    - "9001"
  environment:
    MINIO_ROOT_USER: minio
    MINIO_ROOT_PASSWORD: minio123
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
    interval: 30s
    timeout: 20s
    retries: 3

# starts 3 docker containers running minio server instances.
# using nginx reverse proxy, load balancing, you can access
# it through port 9000.
services:
  minio1:
    <<: *minio-common
    container_name: minio1 # 容器名
    hostname: minio1 # 服务名
    volumes: # 挂载目录
      - /home/data1-1:/data1
      - /home/data1-2:/data2

  minio2:
    <<: *minio-common
    container_name: minio2
    hostname: minio2
    volumes:
      - /home/data2-1:/data1
      - /home/data2-2:/data2

  minio3:
    <<: *minio-common
    container_name: minio3
    hostname: minio3
    volumes:
      - /home/data3-1:/data1
      - /home/data3-2:/data2

  nginx:
    image: nginx:1.19.2-alpine
    container_name: nginx-minio
    hostname: nginx
    volumes: # nginx.conf 配置文件挂载路径
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "19000:9000"
      - "19001:9001"
    depends_on:
      - minio1
      - minio2
      - minio3

## By default this config uses default local driver,
## For custom volumes replace with volume driver configuration.
volumes:
  data1-1:
  data1-2:
  data2-1:
  data2-2:
  data3-1:
  data3-2:
  1. 在minio-kkfileview 目录下创建nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  4096;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;

    # include /etc/nginx/conf.d/*.conf;

    upstream minio {
        server minio1:9000;
        server minio2:9000;
        server minio3:9000;
    }

    upstream console {
        ip_hash;
        server minio1:9001;
        server minio2:9001;
        server minio3:9001;
    }

    # 监听9000端口转发到minio服务
    server {
        listen       9000;
        listen  [::]:9000;
        server_name  localhost;

        # To allow special characters in headers
        ignore_invalid_headers off;
        # Allow any size file to be uploaded.
        # Set to a value such as 1000m; to restrict file size to a specific value
        client_max_body_size 0;
        # To disable buffering
        proxy_buffering off;

        location / {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_connect_timeout 300;
            # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            chunked_transfer_encoding off;

            proxy_pass http://minio;
        }
    }

    # 监听9001转发到minio控制台
    server {
        listen       9001;
        listen  [::]:9001;
        server_name  localhost;

        # To allow special characters in headers
        ignore_invalid_headers off;
        # Allow any size file to be uploaded.
        # Set to a value such as 1000m; to restrict file size to a specific value
        client_max_body_size 0;
        # To disable buffering
        proxy_buffering off;

        location / {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-NginX-Proxy true;

            # This is necessary to pass the correct IP to be hashed
            real_ip_header X-Real-IP;

            proxy_connect_timeout 300;

            # To support websocket
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            chunked_transfer_encoding off;

            proxy_pass http://console;
        }
    }
}
  1. 编写启动脚本
#!/bin/sh

DOCKERHOME=/home/minio-kkfileview # docker-compose.yaml 根路径

BASE_IMAGE_NAME=registry.cn-hangzhou.aliyuncs.com/vote_2020 #镜像仓库地址
BSEE_IMAGE_TAG=1.0.0 # 版本

KKFILEVIEW=$BASE_IMAGE_NAME/kkfileview:$BSEE_IMAGE_TAG # 镜像名称+版本
MINIO=$BASE_IMAGE_NAME/minio:$BSEE_IMAGE_TAG


case "$1" in

	pull)
		echo "* ===============正在拉取共有镜像...."
		time docker pull minio/minio
		echo "* ===============拉取共有镜像成功==================="
		echo "* ===============正在拉取私有镜像..."
		time docker pull $KKFILEVIEW
		time docker pull $MINIO
		echo "* ===============拉取私有镜像成功==================="
		;;
		
	run)
		echo "* ===============开始运行共有镜像..."
		time docker-compose -f $DOCKERHOME/docker-compose-public.yaml up -d
		echo "* ===============等待10S..."
		sleep 10
		echo "* ===============开始运行私有镜像..."
		time docker-compose -f $DOCKERHOME/docker-compose-private.yaml up -d
		echo "* ===============运行成功================"
		;;
		
	pullrun)
        echo "* ===============正在拉取共有镜像...."
		time docker pull minio/minio
		echo "* ===============拉取共有镜像成功==================="
		echo "* ===============正在拉取私有镜像..."
		time docker pull $KKFILEVIEW
		time docker pull $MINIO
		echo "* ===============拉取私有镜像成功==================="
		sleep 3
		echo "* ===============开始运行共有镜像..."
		time docker-compose -f $DOCKERHOME/docker-compose-public.yaml up -d
		echo "* ===============等待10S..."
		sleep 10
		echo "* ===============开始运行私有镜像..."
		time docker-compose -f $DOCKERHOME/docker-compose-private.yaml up -d
		echo "* ===============运行成功================"
		;;
	
    stop)
        echo "* ===============正在停止容器..."
        time docker-compose -f $DOCKERHOME/docker-compose-public.yaml stop
        time docker-compose -f $DOCKERHOME/docker-compose-private.yaml stop
        echo "* ===============停止容器成功==============="
        ;;
    
    restart)
        echo "* ===============正在重启镜像..."
        time docker-compose -f $DOCKERHOME/docker-compose-public.yaml restart
        time docker-compose -f $DOCKERHOME/docker-compose-private.yaml restart
		echo "* ===============重启容器成功==============="
        ;;
		
    *)
        echo "* 命令不存在"
        ;;
		
esac
exit 0

到此就基本完成了,启动脚本 sh start.sh pullrun 拉取并运行镜像。结果如下:
在这里插入图片描述查看镜像与容器:
在这里插入图片描述浏览器访问控制台:
在这里插入图片描述上传文件试试:
在这里插入图片描述下载文件试试:
在这里插入图片描述测试在线预览,就用kkfileview自带页面测试,把刚才我们上传的文件路径copy到下面,注意需要携带http://这里是kkfileview的bug。看源码定位DownloadUtils.downLoad URL url = WebUtils.normalizedURL(urlStr); URL.parse(urlStr).toJavaURL(); 不能识别为携带http开头的url。如何修改这里就不多说了,网上一大堆文章。
在这里插入图片描述点击预览:
在这里插入图片描述注意:这里文件必须是可公共访问的,可设置minio存储桶的访问策略,这里将zhiyi存储桶下的public目录设置为公共可读。当然,为了安全性,你也可以修改预览接口,不传url,传入桶名与对象名进行,后端进行下载并继续后续操作。
在这里插入图片描述有疑问,或文章有错误,欢迎评论区留言。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐