Java实现对象存储的4种方式(本地对象存储、MINIO、阿里云OSS、FastDFS)

文章目录

  • Java实现对象存储的3中方式
    • 1、概述
    • 2、本地对象存储
      • 2.1 配置本地文件相关信息
      • 2.2 通用映射配置 ResourcesConfig
      • 2.3 文件上传业务 LocalSysFileServiceImpl
      • 2.4 上传接口
      • 2.5 演示
    • 3、MINIO
      • 3.1 依赖
      • 3.2 配置
      • 3.3 配置连接信息
      • 3.4. MINIO文件上传业务
      • 3.5 文件上传下载接口
      • 3.6 演示
    • 4、阿里云OSS
      • 功能特性:
      • 使用流程:
      • 安全与合规:
      • 步骤1:添加依赖
      • 步骤2:配置OSS客户端
      • 步骤3:文件上传
      • 步骤4:文件下载
      • 注意事项
    • 5、FastDFS
      • 步骤1:引入依赖
      • 步骤2:初始化FastDFS客户端配置
      • 步骤3:文件上传
      • 步骤4:文件下载
      • 注意事项

Java实现对象存储的3中方式

1、概述

对象存储(Object Storage)是一种数据存储架构,它以对象(Object)为基本单位管理数据,区别于传统的文件存储(按目录层级组织)和块存储(主要用于磁盘和卷)。在对象存储中,每个对象包含数据本身、可变数量的元数据(描述数据的信息)和一个全局唯一的标识符(通常是对象的名称或键)。这种存储模型非常适合处理非结构化数据,如图片、视频、文档等。

对象存储的主要特点包括:

  1. 扁平化命名空间:对象存储没有文件系统的目录树结构,所有对象都存储在一个扁平的命名空间(通常称为“容器”或“桶”Bucket)中,通过对象的唯一标识符访问。
  2. 高度可扩展性:对象存储设计用于海量数据存储,能够容易地水平扩展存储容量,适应不断增长的数据需求。
  3. 元数据灵活性:每个对象可以携带丰富的元数据,使得数据管理和搜索更加灵活高效。
  4. 数据冗余与分布:为了确保数据的高可用性和持久性,对象存储通常会在多个地理位置复制数据,即使某个存储节点发生故障也不会丢失数据。
  5. 基于网络的访问:通过标准的网络协议(如HTTP/HTTPS)和RESTful API访问数据,便于跨平台和远程访问。
  6. 成本效益:由于其规模经济和优化的存储效率,对象存储通常比其他类型的存储更经济,特别是对于大量非频繁访问的数据(冷数据或温数据)。
  7. 安全性:对象存储提供多种安全措施,包括数据加密(静态和传输过程中的)、访问控制列表(ACL)、身份验证机制等,以保护数据免受未授权访问。

对象存储广泛应用于云存储服务、大数据分析、内容分发网络(CDN)、备份与归档、以及许多需要处理大量非结构化数据的应用场景中。

2、本地对象存储

2.1 配置本地文件相关信息

# 本地文件存储
file:# 本地存放的路径地址path: D:/develop/学习/spring-boot3/file# 映射地址prefix: /static# 访问地址domain: http://127.0.0.1:${server.port}

我们通过将文件上传到我们指定的本地存放的路径地址,通过访问地址+映射地址+文件名可以直接访问到本地的这个文件

2.2 通用映射配置 ResourcesConfig

@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{/*** 上传文件存储在本地的根路径*/@Value("${file.path}")private String localFilePath;/*** 资源映射路径 前缀*/@Value("${file.prefix}")public String localFilePrefix;@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry){/** 本地文件上传路径 */registry.addResourceHandler(localFilePrefix + "/**").addResourceLocations("file:" + localFilePath + File.separator);}/*** 开启跨域*/@Overridepublic void addCorsMappings(CorsRegistry registry) {// 设置允许跨域的路由registry.addMapping(localFilePrefix  + "/**")// 设置允许跨域请求的域名.allowedOrigins("*")// 设置允许的方法.allowedMethods("GET");}
}

2.3 文件上传业务 LocalSysFileServiceImpl

@Primary
@Service
@Slf4j
public class LocalSysFileServiceImpl implements ISysFileService {/*** 资源映射路径 前缀*/@Value("${file.prefix}")public String localFilePrefix;/*** 域名或本机访问地址*/@Value("${file.domain}")public String domain;/*** 上传文件存储在本地的根路径*/@Value("${file.path}")private String localFilePath;@Value("${server.servlet.context-path}")private String path;/*** 本地文件上传接口** @param file 上传的文件* @return 访问地址* @throws Exception*/@Overridepublic String uploadFile(MultipartFile file) {try {String name = FileUploadUtils.upload(localFilePath, file);return domain + path + localFilePrefix + name;} catch (Exception e) {log.info("上传文件失败", e);return "";}}
}

2.4 上传接口

@RestController
@Tag(name = "文件控制器")
@RequestMapping("file")
public class SysFileController {private static final Logger log = LoggerFactory.getLogger(SysFileController.class);@Autowiredprivate ISysFileService sysFileService;/*** 本地文件上传请求*/@Operation(summary = "本地文件上传请求")@PostMapping("/uploadStatic")public CommonResult upload(MultipartFile file) {return CommonResult.SUCCESS(sysFileService.uploadFile(file));}}

2.5 演示

上传

在这里插入图片描述

访问
在这里插入图片描述

3、MINIO

3.1 依赖

        <!-- 分布式对象存储minio --><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>${minio.version}</version></dependency>

3.2 配置

# MinIO 分布式文件系统
minio:url: http://127.0.0.1:9000# 账号accessKey: minioadmin# 密码secretKey: minioadmin# MinIO桶名字bucketName: youzi

3.3 配置连接信息

在代码中配置Access Key ID、Secret Access Key和Endpoint,以建立与对象存储服务的连接。

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {/*** 服务地址*/private String url;/*** 用户名*/private String accessKey;/*** 密码*/private String secretKey;/*** 存储桶名称*/private String bucketName;@Beanpublic MinioClient getMinioClient(){return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();}}

3.4. MINIO文件上传业务

我这里使用一个接口对应多个不同实现类的设计模式典型地体现了**策略模式(Strategy Pattern)**的思想。策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以相互替换,让算法的变化独立于使用算法的客户。在这种模式中,一个接口(策略接口)定义了多种行为或算法,而每种行为或算法都有一个具体的实现类。客户端可以通过使用不同的实现类来改变程序的行为,而不需要了解这些类是如何实现的。

在这里插入图片描述

/*** Minio 文件存储** @author ruoyi*/
@Service
@Slf4j
public class MinioSysFileServiceImpl implements ISysFileService
{@Autowiredprivate MinioConfig minioConfig;@Autowiredprivate MinioClient client;/*** Minio文件上传接口** @param file 上传的文件* @return 访问地址* @throws Exception*/@Overridepublic String uploadFile(MultipartFile file){try {String path = "test/";String fileName = path + FileUploadUtils.extractFilename(file);InputStream inputStream = file.getInputStream();PutObjectArgs args = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).stream(inputStream, file.getSize(), -1).contentType(file.getContentType()).build();client.putObject(args);inputStream.close();return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;} catch (Exception e) {log.info("上传文件失败", e);return "";}}@Overridepublic void downloaFile(String fileName, HttpServletResponse response) {try {GetObjectArgs object = GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).build();InputStream stream = client.getObject(object);response.setContentType("application/octet-stream");response.setCharacterEncoding("utf-8");// 设置文件名String downloadName = fileName.substring(fileName.lastIndexOf("/") + 1);response.setHeader("Content-Disposition", "attachment;filename=" + downloadName);OutputStream outputStream = response.getOutputStream();byte[] buf = new byte[1024];int bytesRead;while ((bytesRead = stream.read(buf)) != -1) {outputStream.write(buf, 0, bytesRead);}outputStream.flush();stream.close();outputStream.close();log.info("《==病历Excel文件下载成功,MINIO文件名:{}==》", fileName);} catch (Exception e) {System.err.println("Error streaming file: " + e.getMessage());}}
}

3.5 文件上传下载接口

@RestController
@Tag(name = "文件控制器")
@RequestMapping("file")
public class SysFileController {private static final Logger log = LoggerFactory.getLogger(SysFileController.class);@Autowiredprivate ISysFileService sysFileService;@Autowired@Qualifier("minioSysFileServiceImpl")private ISysFileService minioSysFileServiceImpl;/*** MinIo文件上传请求*/@Operation(summary = "MinIo文件上传请求")@PostMapping("/uploadMinIo")public CommonResult uploadMinIo(MultipartFile file) {return CommonResult.SUCCESS(minioSysFileServiceImpl.uploadFile(file));}/*** MinIo文件上传请求*/@Operation(summary = "MinIo文件下载")@PostMapping("/downloadMinIo")public void downloadMinIo(String fileName, HttpServletResponse response) {minioSysFileServiceImpl.downloaFile(fileName,response);}
}

3.6 演示

上传

在这里插入图片描述

访问
在这里插入图片描述

下载
在这里插入图片描述

4、阿里云OSS

阿里云OSS(Object Storage Service)是阿里巴巴云提供的一种海量、安全、低成本、高可靠的云存储服务。OSS专为互联网和移动应用设计,特别适合存储图片、音视频、文档、网站内容等多种类型的数据。以下是使用阿里云OSS的一些关键点和流程:

功能特性:

  1. 海量存储:支持存储数十亿级别的文件,容量近乎无限扩展。
  2. 高可靠性:数据多重冗余备份,99.999999999%(11个9)的数据持久性。
  3. 高速访问:全球CDN加速,提供低延迟、大带宽的数据访问能力。
  4. 安全性:支持HTTPS、防盗链、STS临时授权、RAM访问控制等安全措施。
  5. 成本效益:按实际使用量计费,无最低消费限制,且长期存储费用较低。
  6. 灵活的API访问:提供基于HTTP/HTTPS的RESTful API接口,支持多语言SDK(包括Java、Python、PHP、Node.js等)。

使用流程:

  1. 注册与实名认证:首先在阿里云官网注册账号并完成实名认证。

  2. 购买与开通OSS服务:在阿里云控制台购买OSS服务并开通。

  3. 创建Bucket:登录OSS控制台,创建一个或多个存储空间(Bucket),用于存储对象。

  4. 上传文件

    :通过控制台或者使用SDK编写代码,将文件上传至指定的Bucket中。

    • 可以直接上传文件,或使用分片上传处理大文件。
  5. 管理文件:在控制台上查看、下载、删除文件,或设置访问权限、生命周期规则等。

  6. 下载与分发:通过URL直接访问或使用CDN加速访问存储在OSS中的文件。

  7. API与SDK集成:在应用中集成OSS SDK,实现自动化文件管理,如在上传、下载、删除等操作中动态调用API。

安全与合规:

  • 设置合适的访问权限,如公有读私有写、私有读写等。
  • 使用RAM(Resource Access Management)进行细粒度的权限控制。
  • 开启日志审计,监控和追踪OSS资源访问情况。

步骤1:添加依赖

确保你的项目中已经包含了阿里云OSS SDK的依赖。如果你使用的是Maven,可以在pom.xml中添加如下依赖:

Xml

<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId>
<!-- 请替换为最新的版本号 --><version>3.10.2</version>
</dependency>

步骤2:配置OSS客户端

在代码中配置OSS客户端,包括Endpoint、AccessKeyId、AccessKeySecret以及Bucket名称。

Java

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;public class OssDemo {public static void main(String[] args) {String endpoint = "<你的Endpoint>";String accessKeyId = "<你的AccessKeyId>";String accessKeySecret = "<你的AccessKeySecret>";String bucketName = "<你的Bucket名称>";// 创建OSSClient实例OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);// 进行上传和下载操作...// 关闭OSSClientossClient.shutdown();}
}

步骤3:文件上传

使用putObject方法上传文件到OSS。

Java

// 上传文件
String uploadFilePath = "<本地文件路径>";
String objectName = "<OSS中的对象键,即上传后的文件名>";
ossClient.putObject(bucketName, objectName, new File(uploadFilePath));
System.out.println("文件上传成功");

步骤4:文件下载

使用getObject方法从OSS下载文件到本地。

Java

// 下载文件
String downloadFilePath = "<本地保存路径>";
String downloadObjectName = "<OSS中的对象键,即要下载的文件名>";
ossClient.getObject(new GetObjectRequest(bucketName, downloadObjectName), new File(downloadFilePath));
System.out.println("文件下载成功");

注意事项

  • 请确保替换上述代码中的<你的Endpoint><你的AccessKeyId><你的AccessKeySecret><你的Bucket名称><本地文件路径><OSS中的对象键>等占位符为实际的值。
  • 在生产环境中,建议使用STS(Security Token Service)临时凭证来增强安全性,避免直接使用AccessKey和SecretKey。
  • 操作完成后记得关闭OSSClient,以释放资源。

以上就是Java程序中使用阿里云OSS实现文件上传和下载的基本步骤。

5、FastDFS

FastDFS,这是一个开源的高性能分布式文件系统,而非FSTFastDfs。在Java程序中使用FastDFS进行文件的上传和下载,通常需要依赖FastDFS的Java客户端库,比如fastdfs-client-java

步骤1:引入依赖

如果是Maven项目,你需要在pom.xml中添加FastDFS客户端的依赖:

Xml

<dependency><groupId>org.csource.fastdfs</groupId><artifactId>fastdfs-client-java</artifactId><!-- 请根据实际情况填写正确的版本号 --><version>最新版本号</version>
</dependency>

步骤2:初始化FastDFS客户端配置

在使用FastDFS客户端之前,需要对其进行初始化,通常通过加载配置文件来完成。配置文件中包含Tracker服务器的地址等信息。

Java

import org.csource.fastdfs.*;public class FastDFSClientExample {static {try {ClientGlobal.init("classpath:fastdfs-client.properties");} catch (IOException e) {e.printStackTrace();throw new RuntimeException("FastDFS Client Init Fail!", e);}}// ... 其他代码
}

步骤3:文件上传

使用TrackerClientStorageClient来上传文件。

Java

public String uploadFile(String filePath) {try {TrackerClient trackerClient = new TrackerClient();TrackerServer trackerServer = trackerClient.getConnection();StorageClient storageClient = new StorageClient(trackerServer, null);// 上传文件,并获取文件的存储信息(组名和文件路径)String[] uploadResults = storageClient.upload_file(filePath, "jpg", null);if (uploadResults != null && uploadResults.length == 2) {return uploadResults[0] + "/" + uploadResults[1];} else {throw new RuntimeException("文件上传失败!");}} catch (Exception e) {e.printStackTrace();throw new RuntimeException("文件上传异常!", e);}
}

步骤4:文件下载

下载文件需要根据文件的存储信息(组名和文件路径)来进行。

Java

public void downloadFile(String groupName, String remoteFileName, String localFilePath) {try {TrackerClient trackerClient = new TrackerClient();TrackerServer trackerServer = trackerClient.getConnection();StorageClient storageClient = new StorageClient(trackerServer, null);// 下载文件到本地byte[] fileBytes = storageClient.download_file(groupName, remoteFileName);if (fileBytes != null) {FileOutputStream out = new FileOutputStream(localFilePath);out.write(fileBytes);out.flush();out.close();System.out.println("文件下载成功");} else {throw new RuntimeException("文件下载失败!");}} catch (Exception e) {e.printStackTrace();throw new RuntimeException("文件下载异常!", e);}
}

注意事项

  • 确保fastdfs-client.properties配置文件正确配置了Tracker服务器地址。
  • 上传和下载的文件名(特别是远程文件名)应遵循FastDFS的规定,有时需要指定文件扩展名以供FastDFS进行正确的MIME类型识别。
  • 在实际应用中,应当适当处理异常,并考虑资源的释放和错误的重试逻辑。

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

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

相关文章

高性价比、超强功能的开源工单解决方案

在企业日常运营中&#xff0c;工单管理系统是不可或缺的工具。高效的工单管理不仅能提升工作效率&#xff0c;还能显著提高客户满意度。今天&#xff0c;我们为您推荐搭贝工单派单系统——一款超高性价比、功能齐全的开源工单管理系统。 &#x1f50d; 为什么选择搭贝工单派单…

LangChain入门开发教程(一):Model I/O

官方文档&#xff1a;https://python.langchain.com/docs/get_started/introduction/ LangChain是一个能够利用大语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;能力进行快速应用开发的框架&#xff1a; 高度抽象的组件&#xff0c;可以像搭积木一样&a…

【PB案例学习笔记】-13 徒手做个电子时钟

写在前面 这是PB案例学习笔记系列文章的第11篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

python基础-数据结构-leetcode刷题必看-queue---队列-python的底层构建

文章目录 队列双端队列 deque底层存储deque接口1. __init__(self, iterable: Iterable[_T], maxlen: int | None None) -> None2. append(self, __x: _T) -> None3. appendleft(self, __x: _T) -> None4. copy(self) -> Self5. count(self, __x: _T) -> int6. …

java项目启动报错

java项目启动报错&#xff1a;java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field ‘com.sun.tools.javac.tree.JCTree qualid’ 原因&#xff1a;编译和运行的版本不一样 点击idea文件 点击项目结构 把这两个版本…

软件架构设计属性之一:功能性属性浅析

引言 软件架构设计属性中的功能性属性是评估软件架构是否满足其预定功能需求的关键指标。功能性属性确保软件能够执行其设计中的任务&#xff0c;并提供所需的服务。以下是对软件架构设计中功能性属性的浅析&#xff1a; 一、定义 功能性属性是指软件系统所具备的功能特性&a…

解决Android studio 一直提示下载gradle-xxx-all.zip问题

今天用AndroidStdiod打开一个新工程的时候&#xff0c;发现项目一直卡在正在下载gradle-xxx-all.zip的任务上&#xff0c;网络出奇的慢&#xff0c;即使配了VPN也无济于事&#xff0c;于是按照以往经验&#xff1a;将gradle-xxx-all.zip下载到.gradle\gradle\wrapper\dists目录…

【ESP32之旅】ESP32 PlatformIO 固件单独烧录

背景 有时候使用PIO编写的代码需要发给客户去验证&#xff0c;相比较于发送源码直接发送bin文件&#xff0c;更加的安全而且高效。不用担心源码的泄漏&#xff0c;也不用帮客户配置PIO环境。 操作方法 1.编译 首先进行代码编译&#xff0c;如编译成功会在 .pio\build\airm2…

汽车电子学习【车载网络CAN/LIN】

车载网络CAN/LIN知识总结 STM32F1开发板测试 STM32测试程序 /** CAN 通信报文内容设置*/ void CAN_SetMsg(void) { #if CAN_STDTxMessage.StdId 0x12;TxMessage.IDE CAN_ID_STD; #elseTxMessage.ExtId 0x1314; //使用的扩展IDTxMessage.IDE CAN_ID_EXT; //扩展模式 #…

Django 做migrations时出错,解决方案

在做migrations的时候&#xff0c;偶尔会出现出错。 在已有数据的表中新增字段时&#xff0c;会弹出下面的信息 运行这个命令时 python manage.py makemigrationsTracking file by folder pattern: migrations It is impossible to add a non-nullable field ‘example’ to …

Linux---网络相关配置

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 一台主机需要配置必要的网络信息&#xff0c;才可以连接到互联网&#xff0c;需要的配置网络信息包括IP&#xff0c;子网掩码&#xff0c;网关和DNS。 一.查看网络信息 查看IP信息可以通…

echarts高级应用

目录 一、显示相关 1.1、主题 1.1.1、内置主题 1.1.2、自定义主题 1.2、调色盘和颜色渐变 1.2.1、主题调色盘<全局调色盘<局部调色盘 1.2.2、线性渐变(linear)、径向渐变(radial) 1.3、直接样式和高亮样式 1.3.1、直接样式 1.3.2、高亮样式 1.4、图表自适应 …

软件架构设计属性之三:结构性属性浅析

文章目录 引言一、结构性属性的定义二、结构性属性的关键要素1. 组件化2. 模块化3. 层次化4. 接口定义5. 数据流6. 依赖管理 三、结构性属性的设计原则1. 高内聚低耦合2. 松耦合3. 清晰的接口4. 可维护性5. 可扩展性 四、结构性属性的实现策略1. 组件划分2. 模块化设计3. 接口设…

【AREngine BUG 解决方法】无法获取有效的相机图像尺寸

近期拿了一台 华为mate20 Pro的手机&#xff0c;在运行AR示例的过程中出现了黑屏。 问题排查 SDK版本&#xff1a;com.huawei.hms:arenginesdk:3.7.0.3 定位 经排查&#xff0c;发现(ARCamera对象的相机内参) getImageDimensions()返回的图像尺寸的width和height都为0。 这…

Kong api网关实战教程

1. kong介绍 Kong是一款基于OpenResty(NginxLua模块)编写的高可用、易扩展的&#xff0c;由Mashape公司开源的API Gateway项目。Kong是基于NGINX和Apache Cassandra或PostgresQL构建的&#xff0c;能据供易于使用的RSTTAP[来操作和配置API管理系统&#xff0c;所以它可以水平扩…

【上】王树森《小红书推荐系统公开课》- 课程笔记(推荐系统基础、召回、排序)

写在前面 本文为王树森老师《小红书推荐系统公开课》的课程笔记 课程来源&#xff1a;ShusenWang的个人空间-ShusenWang个人主页-哔哩哔哩视频 (bilibili.com)课程资料&#xff1a;GitHub - wangshusen/RecommenderSystem 由于篇幅较长&#xff0c;分为【上】【下】两篇文章…

【busybox记录】【shell指令】unlink

目录 内容来源&#xff1a; 【GUN】【unlink】指令介绍 【busybox】【unlink】指令介绍 【linux】【unlink】指令介绍 使用示例&#xff1a; 删除文件 - 默认 常用组合指令&#xff1a; 指令不常用/组合用法还需继续挖掘&#xff1a; 内容来源&#xff1a; GUN &#x…

深入解析Web前端三大主流框架:Angular、React和Vue

Web前端三大主流框架分别是Angular、React和Vue。下面我将为您详细介绍这三大框架的特点和使用指南。 Angular 核心概念: 组件(Components): 组件是Angular应用的构建块,每个组件由一个带有装饰器的类、一个HTML模板、一个CSS样式表组成。组件通过输入(@Input)和输出(…

【OrangePi AIpro】开箱初体验以及OAK深度相机测试

1. 简介 Orangepi AIPRO 是一款采用昇腾AI技术路线&#xff0c;集成4核64位处理器AI处理器的单板计算机&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接eMMC模块&#xff0c;支持双4K高清输出。 Orange Pi AIpr…

数字图像处理系列 | 线性滤波(高斯滤波)(3)

我们知道了什么是 线性平移不变系统是在做卷积操作 之后&#xff0c;我们发展出了一些非常简单的 线性滤波&#xff0c; 去增强图片&#xff0c;提取图片特征 文章目录 1. 卷积如何在离散图片中工作的Vis 原图和mask做卷积时发生了什么首先&#xff0c;如何得到 (i.j)位置的卷积…