当前位置: 首页 > news >正文

搭建高性能分布式存储-minio

文章目录

    • 搭建高性能分布式存储-minio
      • Docker搭建minio(单机部署+纠删码模式)⭐
      • 创建minio的bucket(桶)⭐
      • SpringBoot+minio项目实战 ⭐
        • 1:导入minio的maven依赖
        • 2:编写MinioProperties.class
        • 3:application.yml:
        • 4:MinioConfig.class配置类
        • 5:ResponseResult(统一响应结果)
        • 6:ResponseType(响应类型枚举类)
        • 7:UploadController.class(上传接口)
        • 8:上传service接口
        • 9:上传service接口实现类:

搭建高性能分布式存储-minio

Docker搭建minio(单机部署+纠删码模式)⭐

  • 1:使用minio Docker镜像,在在单机中使用EC纠删码模式部署,8块盘中启动minio服务:
    • 注意:MINIO_ROOT_PASSWORD初始化默认密码长度必须要达到8位。
docker run --name minio -d \-p 9000:9000 \-p 50000:50000 \-v /mnt/minio/data1:/data1 \-v /mnt/minio/data2:/data2 \-v /mnt/minio/data3:/data3 \-v /mnt/minio/data4:/data4 \-v /mnt/minio/data5:/data5 \-v /mnt/minio/data6:/data6 \-v /mnt/minio/data7:/data7 \-v /mnt/minio/data8:/data8\-e MINIO_ROOT_USER="root" \-e MINIO_ROOT_PASSWORD="12345678" \minio/minio:latest server /data{1...8} --console-address ":50000"
  • 2:访问minio控制台:(http://服务器ip:50000/)

创建minio的bucket(桶)⭐

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

SpringBoot+minio项目实战 ⭐

1:导入minio的maven依赖
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.3</version>
</dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
</dependency>
2:编写MinioProperties.class
package com.boot.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;/*** 高性能分布式存储-minio属性类** @author youzhengjie* @date 2022/10/28 00:22:48*/
@Component
@Data
@ConfigurationProperties(prefix = "minio")
@EnableConfigurationProperties({MinioProperties.class
})
public class MinioProperties {/*** minio的通信端点(url),和控制台端点不一样*/private String endpoint;/*** 说白了就是minio的帐号*/private String accessKey;/*** 说白了就是minio的密码*/private String secretKey;/*** 指定操作哪一个桶*/private String bucketName;
}
3:application.yml:
  • 注意:记得把下面的配置属性修改成你自己的!
minio:endpoint: http://192.168.184.123:9000access-key: rootsecret-key: 12345678bucket-name: security-jwt2-bucket
4:MinioConfig.class配置类
  • 作用是将MinioClient交给Spring管理,方便后续直接@AutoWired注入即可使用)
package com.boot.config;import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** minio配置类** @author youzhengjie* @date 2022/10/28 00:30:31*/
@Configuration
public class MinioConfig {@Autowiredprivate MinioProperties minioProperties;/*** minio-client bean** @return {@link MinioClient}*/@Beanpublic MinioClient minioClient(){return MinioClient.builder()//配置minio的通信端点(url),和控制台端点不一样.endpoint(minioProperties.getEndpoint())//配置minio的帐号密码.credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey()).build();}}
5:ResponseResult(统一响应结果)
package com.boot.data;import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 统一响应结果*/
@JsonInclude(JsonInclude.Include.NON_NULL) //为null的字段不进行序列化
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ResponseResult<T> {/*** 响应状态码*/private Integer code;/*** 响应状态码对应的信息提示*/private String msg;/*** 返回给前端的数据*/private T data;public ResponseResult(Integer code, String msg) {this.code = code;this.msg = msg;}public ResponseResult(Integer code, T data) {this.code = code;this.data = data;}}
6:ResponseType(响应类型枚举类)
package com.boot.enums;/*** 响应类型枚举类* @author youzhengjie* @date 2022-09-22 22:47:21*/
public enum ResponseType {/*** 文件操作状态*/IMAGE_UPLOAD_SUCCESS(901,"图片上传成功"),IMAGE_UPLOAD_ERROR(902,"图片上传失败"),FILE_FORMAT_UNSUPPORT(903,"不支持该文件格式,上传失败"),FILE_DELETE_SUCCESS(904,"文件删除成功"),FILE_DELETE_ERROR(905,"文件删除失败"),;private int code;private String message;ResponseType(int code, String message) {this.code = code;this.message = message;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
7:UploadController.class(上传接口)
@RestController
@Api("上传接口")
@RequestMapping(path = "/upload")
@Slf4j
public class UploadController {@Autowired@Qualifier("minioUploadServiceImpl") //指定spring注入的实现类private OssUploadService ossUploadService;/*** 上传头像** @param avatarFile 头像文件(名字一定要和el-upload的:name属性一致)* @return {@link ResponseResult}*/@OperationLog("上传头像")@PostMapping(path = "/avatar")@ApiOperation("上传头像")public ResponseResult uploadAvatar(MultipartFile avatarFile){ResponseResult result = ossUploadService.imageUpload(avatarFile);return result;}/*** 文件删除** @param fileFullName 文件名* @return {@link ResponseResult}*/@OperationLog("文件删除")@DeleteMapping(path = "/fileDelete")@ApiOperation("文件删除")public ResponseResult fileDelete(@RequestParam("fileFullName") String fileFullName){return ossUploadService.fileDelete(fileFullName);}/*** 文件下载** @param fileName 文件名称* @param response 响应*/@GetMapping(path = "/fileDownload")@ApiOperation("文件下载")public void fileDownload(@RequestParam("fileName") String fileName, HttpServletResponse response){ossUploadService.fileDownload(fileName,response);}
}
8:上传service接口
package com.boot.service;import com.boot.data.ResponseResult;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;/*** oss上传service接口* @author youzhengjie* @date 2022-10-06 23:13:28*/
public interface OssUploadService {/*** oss图片上传* @param imageFile* @return 上传结果*/ResponseResult imageUpload(MultipartFile imageFile);/*** oss文件删除* @param fileFullName 文件全名,** @return 删除结果*/ResponseResult fileDelete(String fileFullName);/*** 文件下载** @param fileName 文件名称* @param response 响应*/default void fileDownload(String fileName, HttpServletResponse response){throw new UnsupportedOperationException("该实现类暂不支持文件下载操作,请切换到其他实现类!");}}
9:上传service接口实现类:
package com.boot.service.impl;import com.boot.config.MinioProperties;
import com.boot.data.ResponseResult;
import com.boot.enums.ResponseType;
import com.boot.service.OssUploadService;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;/*** minio上传服务service impl** @author youzhengjie* @date 2022/10/28 13:59:35*/
@Service("minioUploadServiceImpl")
@Slf4j
public class MinioUploadServiceImpl implements OssUploadService {@Autowiredprivate MinioProperties minioProperties;/*** 注入MinioClient,用于操作minio*/@Autowiredprivate MinioClient minioClient;/*** 检查文件是否是图片类型* @param originalFilename* @return true代表是图片,false则不是图片*/private boolean isImage(String originalFilename){//将文件名全部变小写String lowerOriginalFilename = originalFilename.toLowerCase();return lowerOriginalFilename.endsWith(".jpg") ||lowerOriginalFilename.endsWith(".png") ||lowerOriginalFilename.endsWith(".jpeg");}/*** minio图片上传** @param imageFile 图像文件* @return {@link ResponseResult}*/@Overridepublic ResponseResult imageUpload(MultipartFile imageFile) {//封装响应结果ResponseResult<Object> result = new ResponseResult<>();try {//获取上传前的文件原名String oldFileName = imageFile.getOriginalFilename();//如果不是图片则直接返回if(!isImage(oldFileName)){result.setCode(ResponseType.FILE_FORMAT_UNSUPPORT.getCode());result.setMsg(ResponseType.FILE_FORMAT_UNSUPPORT.getMessage());return result;}//以日期作为目录,每一天的图片都会放到不同的目录下,方便管理String fileDir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/"));//UUID文件名String uuidFileName = UUID.randomUUID().toString().replaceAll("-", "");//获取文件后缀名 .jpgString fileSuffix= oldFileName.substring(oldFileName.lastIndexOf("."));//上传到minio中的新的图片文件名String newFileName = new StringBuilder().append(fileDir).append(uuidFileName).append(fileSuffix).toString();//获取文件流InputStream inputStream = imageFile.getInputStream();//获取文件大小long size = imageFile.getSize();//获取内容类型String contentType = imageFile.getContentType();//构建文件上传所需要的东西(PutObjectArgs)PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(minioProperties.getBucketName()).object(newFileName).stream(inputStream, size, -1).contentType(contentType).build();//开始进行minio文件上传minioClient.putObject(putObjectArgs);//获取该上传到minio的文件的url(使外网可以访问)String fileUrl=minioProperties.getEndpoint()+"/"+minioProperties.getBucketName()+"/"+newFileName;result.setCode(ResponseType.IMAGE_UPLOAD_SUCCESS.getCode());result.setMsg(ResponseType.IMAGE_UPLOAD_SUCCESS.getMessage());result.setData(fileUrl);return result;}catch (Exception e){e.printStackTrace();result.setCode(ResponseType.IMAGE_UPLOAD_ERROR.getCode());result.setMsg(ResponseType.IMAGE_UPLOAD_ERROR.getMessage());return result;}}/*** minio文件删除** @param fileFullName 文件全名 。格式例如:2022/10/28/4f74aa358a4548d4860c110ebec3831f.jpg* @return {@link ResponseResult}*/@Overridepublic ResponseResult fileDelete(String fileFullName) {//封装响应结果ResponseResult<Object> result = new ResponseResult<>();try {RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileFullName).build();minioClient.removeObject(removeObjectArgs);result.setCode(ResponseType.FILE_DELETE_SUCCESS.getCode());result.setMsg(ResponseType.FILE_DELETE_SUCCESS.getMessage());return result;}catch (Exception e){e.printStackTrace();result.setCode(ResponseType.FILE_DELETE_ERROR.getCode());result.setMsg(ResponseType.FILE_DELETE_ERROR.getMessage());return result;}}/*** minio文件下载。** @param fileName 文件名称 。格式例如:2022/10/28/4f74aa358a4548d4860c110ebec3831f.jpg* @param response 响应*/@Overridepublic void fileDownload(String fileName, HttpServletResponse response) {try {// 获取对象信息StatObjectArgs statObjectArgs = StatObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileName).build();StatObjectResponse statObject = minioClient.statObject(statObjectArgs);/*** 描述: content-type 指示响应内容的格式* content-disposition 指示如何处理响应内容。* 一般有两种方式:* inline:直接在页面显示-预览* attachment:以附件形式下载-下载*/response.setContentType(statObject.contentType());
//            response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(fileName, "UTF-8"));response.setHeader("Content-Disposition", "attachment; filename=" +URLEncoder.encode(fileName, "UTF-8"));InputStream inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileName).build());IOUtils.copy(inputStream,response.getOutputStream());}catch (Exception e){throw new RuntimeException("文件下载失败");}}
}

相关文章:

搭建高性能分布式存储-minio

文章目录 搭建高性能分布式存储-minioDocker搭建minio&#xff08;单机部署纠删码模式&#xff09;⭐创建minio的bucket&#xff08;桶&#xff09;⭐SpringBootminio项目实战 ⭐1&#xff1a;导入minio的maven依赖2&#xff1a;编写MinioProperties.class3&#xff1a;applica…...

leetCode 137. 只出现一次的数字 II(拓展篇) + 模5加法器 + 真值表(数字电路)

leetCode 137. 只出现一次的数字 II 题解可看我的往期文章 leetCode 137. 只出现一次的数字 II 位运算 模3加法器 真值表&#xff08;数字电路&#xff09; 有限状态机-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/134138112?spm1001.2014.3001.5501…...

docker导致root空间满进入不了系统解决方案

由于docker建立镜像会产生很多缓存文件&#xff0c;最终导致root目录满&#xff0c;进入不了系统 df -h docker默认路径是在/var/lib/docker下 可以通过命令查看docker占用空间 docker system df 如果占用空间太大 可用以下命令清理 $ docker image prune -h Flag shorth…...

uni-app遮罩遮住小程序tabbar

uni-app遮罩遮住小程序tabbar 1、用uni-app自带的方法显示隐藏 //通过弹窗显隐控制导航栏的显示和隐藏 const popupChange e >{if(e.show){//隐藏tabbaruni.hideTabBar()}else{//显示tabbaruni.showTabBar()}state.searchIcon e.show } //通过弹窗显隐控制导航栏的显示和…...

Flink on yarn 加载失败plugins失效问题解决

Flink on yarn 加载失败plugins失效问题解决 flink版本&#xff1a;1.13.6 1. 问题 flink 任务运行在yarn集群,plugins加载失效,导致通过扩展资源获取任务参数失效 2. 问题定位 yarn容器的jar包及插件信息,jar包是正常上传 源码定位 加载plugins入口&#xff0c;TaskMana…...

显卡服务器的特点和优势在哪里

随着科技的发展以及人们对于计算机性能的需求提高&#xff0c;显卡服务器是主要使用图形处理器进行计算和运算&#xff0c;拥有更加强大的计算能力&#xff0c;今天小编就来给大家讲一讲显卡服务器的特点和优势是什么&#xff01; 1.高可靠性&#xff1a;显卡服务器采用高品质的…...

c++设计模式二:原型模式

使用场景&#xff1a;当需要构建多个相同的类对象时&#xff0c;而且该类对象结构较为复杂&#xff0c;如果每个都重新组织构建会很麻烦。 其实&#xff0c;就是写一个拷贝构造函数&#xff0c;或者写一个拷贝每个成员变量的clone()方法。 举例说明&#xff1a;比如一个相亲网站…...

【Qt控件之QMessageBox】详解

Qt控件之QMessageBox 描述基于属性的API富文本和文本格式属性严重程度以及图标和Pixmap属性静态函数API 高级用法默认按钮和退出按钮示例使用场景 描述 QMessageBox类提供了一个模态对话框&#xff0c;用于通知用户或向用户提问并接收答案。 消息框显示一个主要文本以提醒用户…...

SSH安全登录远程主机

SSH服务器简介 SSH即Security SHell的意思&#xff0c;它可以将连线的封包进行加密技术&#xff0c;之后进行传输&#xff0c;因此相当的安全。 SSH是一种协议标准&#xff0c;其目的是实现安全远程登录以及其它安全网络服务。 SSH协定&#xff0c;在预设的状态下&#xff0c;…...

揭秘!产品经理提升效率的秘密武器:10款AI生成PPT工具

AI的爆炸式增长表现令人惊艳&#xff0c;现有的各类AI工具正在重塑各行各业&#xff0c;不同程度地提高人们的工作效率&#xff0c;并有望创造新的职业机会。但是&#xff0c;面对市面上数量众多的AI工具&#xff0c;且每周都会蹦出新的产品&#xff0c;即便是以好奇心富称的产…...

Oracle修改带数据的字段类型

insert into TNW_FUND_SELORG(TFDINFOID,TSOINFOID) select TFD_INFO_ID,TSO_INFO_ID from TFD_SEL_FUNDLINK_TO_OLDFUNDWEB_DB /*修改原字段名*/ ALTER TABLE 表名 RENAME COLUMN 字段名 TO 字段名1; /*添加一个和原字段同名的字段*/ ALTER TABLE 表名 ADD 字段名 VARCHAR…...

WebService接口方式和Restful接口这两者有什么区别和相同点

WebService和RESTful接口都是用于在网络上进行通信和数据交换的技术&#xff0c;但它们在设计和使用上有一些重要的区别和相似之处。 相同点&#xff1a; 基于HTTP协议&#xff1a;无论是WebService还是RESTful接口&#xff0c;它们都是通过HTTP协议进行通信的。 支持多种数据…...

jenkins自动化操作步骤(gitblit)

1、登陆地址&#xff1a; http://xxxxxxxxx.org:xxxx/ admin/xxxx 2、创建任务 选择构建一个maven项目 3、配置 最多只保留一天一个任务 选择git仓库和账号密码 选择代码对应分支 build项&#xff1a; 1&#xff09;使用父项目的pom文件&#xff1a;k56-boot/pom.xml 2&…...

centos中mongodb设置服务自启动并 允许远程IP访问

安装mongodb参考 注意的是配置文件需要把journal设置为true 制作为系统服务 创建MongoDB服务文件。运行以下命令创建服务文件/etc/systemd/system/mongod.service&#xff1a; vi /etc/systemd/system/mongod.service [Unit] DescriptionMongoDB Database Server Documenta…...

实时定位和配送追踪:开发万岳同城外卖APP的关键技术特性

随着生活节奏的不断加快&#xff0c;外卖服务已经成为许多人日常生活中不可或缺的一部分。无论是工作日的午餐&#xff0c;还是周末的家庭聚会&#xff0c;外卖APP已经成为满足各种美食需求的首选方式。然而&#xff0c;同城外卖APP的成功不仅仅取决于美味的食物选择&#xff0…...

数据库强化(3.存储过程)

1.什么是存储过程&#xff1f; 存储过程&#xff08;Stored Procedure&#xff09;是一种在数据库中存储复杂程序&#xff0c;以便外部程序调用的一种数据库对象。MySQL 5.0 版本开始支持存储过程。 它是为了完成特定功能的SQL语句集&#xff0c;经编译创建并保存在数据库中&a…...

雅思小作文笔记

mostly from Simon’s methods and techniques remember the task is describe what you see, not give an opinion. Just write a report.no conclusion, just a summary(the overview) Question type 小作文的题目类型大致如上 Simon所述&#xff0c;在描述数字的时候&…...

Java List Set Map

一、List 1.1 ArrayList 1.2 LinkedList 二、Set 2.1 HashSet 2.2 TreeSet 2.3 LinkedHashSet 三、Map 3.1 HashMap 3.2 TreeMap 3.3 LinkedHashMap 四、对比 类型底层结构重复null值场景备注查询删除新增ListArrayList动态数组可允许快速随机访问元素0(1)0(n)尾部增加0&a…...

【数据结构】数组和字符串(十三):链式字符串的基本操作(串长统计、查找、复制、插入、删除、串拼接)

文章目录 4.3 字符串4.3.1 字符串的定义与存储4.3.2 字符串的基本操作&#xff08;链式存储&#xff09;1. 结构体2. 初始化3. 判空4. 串尾添加5. 打印6. 串长统计7. 查找8. 复制9. 插入10. 删除11. 串拼接12. 销毁13. 主函数14. 代码整合 4.3 字符串 字符串(String)是由零个或…...

Python3 获取当前服务器公网 IP 地址

有同学问我如何使用 Python 获取服务器公网的 IP 地址呢&#xff1f;我测试几个发现&#xff0c;方法有很多&#xff0c;好用的就发现一种&#xff0c;即直接使用 Python 自带的 socket 包。 代码示例&#xff1a; # 获取主机 IP dgram socket.socket(socket.AF_INET, socke…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

k8s从入门到放弃之Pod的容器探针检测

k8s从入门到放弃之Pod的容器探针检测 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;容器探测是指kubelet对容器执行定期诊断的过程&#xff0c;以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...

【工具教程】多个条形码识别用条码内容对图片重命名,批量PDF条形码识别后用条码内容批量改名,使用教程及注意事项

一、条形码识别改名使用教程 打开软件并选择处理模式&#xff1a;打开软件后&#xff0c;根据要处理的文件类型&#xff0c;选择 “图片识别模式” 或 “PDF 识别模式”。如果是处理包含条形码的 PDF 文件&#xff0c;就选择 “PDF 识别模式”&#xff1b;若是处理图片文件&…...