上传多张图片

news2024/10/10 5:17:00

上传多张图片时需要在对应类中增加图像地址的数组(加上数据库不存在该字段注解),在逻辑层将多张图片的地址进行拼接一起,存入数据库。

minio工具类 
package com.custhitahi.zhjc.util;

import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.DeleteObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;


/**
 * @author turnersun
 * @date 2022/6/17 - 16:31
 */
@Slf4j
@PropertySource("classpath:upload.properties")
@Component
public class MinioUtil {

    /** minio地址+端口号 */
    @Value("${minio.url}")
    private String url;

    /** minio用户名 */
    @Value("${minio.user}")
    private String user;

    /** minio密码 */
    @Value("${minio.password}")
    private String password;

    /** 桶的名称 */
    @Value("${minio.bucketName}")
    private String bucketName;

    /** 域名 */
    @Value("${minio.domain}")
    private String domain;


    private static MinioClient minioClient;

    /**
     * 不排序
     */
    public final static boolean NOT_SORT = false;

    /**
     * 初始化minio配置
     */
    @PostConstruct
    public void init() {
        try {
            minioClient = MinioClient.builder().endpoint(url).credentials(user,password).build();
            if(!isBucketExist()){
                createBucket();
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("初始化minio配置异常: 【{ }】", e.fillInStackTrace());
        }
    }

    /**
     * 存储桶是否存在
     * @return true/false
     */
    @SneakyThrows
    public boolean isBucketExist(){
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 创建存储桶
     */
    @SneakyThrows
    public void createBucket(){
        minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
    }


    /**
     * 获取访问对象的外链地址
     * @param objectName 对象名称
     * @return viewUrl
     */
    @SneakyThrows
    public String getObjectUrl(String objectName){
        String ori = minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
        String url =  ori.substring(0, ori.indexOf("?"));
        return domain+url.substring(url.indexOf("9000")+5);
    }
    @SneakyThrows
    public String getObjectUrlWithBucket(String objectName,String bucketName){
        String ori = minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
        String url =  ori.substring(0, ori.indexOf("?"));
        return domain+url.substring(url.indexOf("9000")+5);
    }
    /**
     * 上传本地文件
     * @param objectName 欲上传的本地文件对象的名称
     * @param filePath 本地文件路径
     */
    @SneakyThrows
    public void uploadFile(String objectName, String filePath){
        minioClient.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .filename(filePath)
                        .build());
    }
    public void uploadFile(String objectName, MultipartFile file) throws Exception {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .contentType(file.getContentType())
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .build());
    }
    public void uploadFile(String objectName, InputStream stream, String size) throws Exception {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(stream, Long.parseLong(size), -1)
                        .build());
    }
    @SneakyThrows
    public void uploadFileWithBucket(String bucketName,String objectName, String filePath){
        minioClient.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .filename(filePath)
                        .build());
    }
    /**
     * 下载文件
     * @param fileName 文件名
     * @return 文件流
     */
    @SneakyThrows(Exception.class)
    public InputStream download(String fileName) {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .build());
    }
    @SneakyThrows(Exception.class)
    public InputStream downloadWithBucket(String fileName,String bucketName) {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .build());
    }





    /**
     * 删除对象
     * @param objectName
     * @return true/false
     */
    @SneakyThrows
    public boolean removeObject(String objectName){
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
        return true;
    }

    /**
     * 批量删除对象
     * @param objectNames
     * @return true/false
     */
    public boolean removeObjects(List<String> objectNames){
        List<DeleteObject> deleteObjects = new ArrayList<>(objectNames.size());
        for (String objectName : objectNames){
            deleteObjects.add(new DeleteObject(objectName));
        }
        minioClient.removeObjects(
                RemoveObjectsArgs.builder()
                        .bucket(bucketName)
                        .objects(deleteObjects)
                        .build()
        );
        return true;
    }


    /**
     * 将分钟数转换为秒数
     * @param expiry 过期时间(分钟数)
     * @return expiry
     */
    private static int expiryHandle(Integer expiry){
        expiry = expiry * 60;
        if (expiry > 604800){
            return 604800;
        }
        return expiry;
    }

    static class Str2IntComparator implements Comparator<String> {
        private final boolean reverseOrder; // 是否倒序
        public Str2IntComparator(boolean reverseOrder) {
            this.reverseOrder = reverseOrder;
        }
        @Override
        public int compare(String arg0, String arg1) {
            Integer intArg0 = Integer.parseInt(arg0.substring(arg0.indexOf("/") + 1,arg0.lastIndexOf(".")));
            Integer intArg1 = Integer.parseInt(arg1.substring(arg1.indexOf("/") + 1,arg1.lastIndexOf(".")));
            if(reverseOrder) {
                return intArg1 - intArg0;
            } else {
                return intArg0 - intArg1;
            }
        }
    }
}
控制层 
    
    @Resource
    private MinioUtil minioUtil;

    String objectName = "invoice/";


    @RequestMapping("/uploadInvoice")
    public Result uploadInvoice(MultipartRequest multipartRequest) throws Exception {
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        String url = null;
        for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
            MultipartFile file = entry.getValue();
            String originalFileName = file.getOriginalFilename();
            String mainName = FileUtil.mainName(originalFileName);//aaa
            String extName = FileUtil.extName(originalFileName);//png
            String fileName = System.currentTimeMillis() + "_" + mainName + "." + extName;
            //将文件上传到图床
            minioUtil.uploadFile(objectName + fileName, file);
            url = minioUtil.getObjectUrl(objectName + fileName);
        }
        return ResultFactory.successWithData(url);
    }
服务层
 @Transactional
    @Override
    public int addPurchaseDetail(FireconPurchaseDetail fireconPurchaseDetail) {
        int res = -1;
        // 参数判空处理
        if(ObjectUtil.isEmpty(fireconPurchaseDetail)) {
            throw new NullPointerException();
        }
        try {
            String result = String.join(",", fireconPurchaseDetail.getImageUrls());
            fireconPurchaseDetail.setImg(result);
            // 保存到数据库
            fireconPurchaseDetail.setApplicationDate(LocalDateTime.now().toLocalDate());
            fireconPurchaseDetail.setApplicationMoney(fireconPurchaseDetail.getApplicationPrice().multiply(fireconPurchaseDetail.getApplicationNum()));
            fireconPurchaseDetailMapper.insert(fireconPurchaseDetail);
            res = fireconPurchaseRequestMapper.updateTotal(fireconPurchaseDetail.getRequestId());
        } catch (Exception e) {
            throw e;
        }
        return res;
    }
实体类
//接收前端传来的多张图片地址,数据库不存在该字段,后端做字符串拼接后存入img字段
    @TableField(exist=false)
    private String[] imageUrls;

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

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

相关文章

基于Arduino的超声波和舵机模块集成使用

一.超声波模块和舵机模块集成使用 超声波模块&#xff1a;HC-SR04舵机模块&#xff1a;SG90目的&#xff1a;通过Arduino UNO核心板控制舵机旋转到不同位置&#xff0c;同时获取不同位置超声波模块和障碍物间的距离&#xff0c;配合控制算法&#xff0c;进行基于超声波智能避障…

需求10——通过改一个小bug来学习如何定位问题

在浏览我之前完成的一些小需求时&#xff0c;我发现了一个非常有价值的需求。这个需求可以让我深入了解系统中关于故障上报的功能。通过完善这个需求&#xff0c;我能够全面掌握整个故障上报的流程。 这个需求主要是关于故障上报流程中出现的问题。当前的流程如下&#xff1a;…

ML 系列:机器学习和深度学习的深层次总结(16) — 提高 KNN 效率-使用 KD 树和球树实现更快的算法

一、说明 在机器学习系列的第 16 节&#xff0c;我们重点介绍了提高 K 最近邻 &#xff08;KNN&#xff09; 算法的效率&#xff0c;这是一种广泛用于分类和回归任务的方法。虽然 KNN 简单有效&#xff0c;但对于大型数据集来说&#xff0c;其计算成本可能会令人望而却步。为了…

基于SpringBoot问卷调查系统小程序【附源码】

基于SpringBoot问卷调查系统小程序 效果如下&#xff1a; 管理员登录界面 管理员功能界面 调查人管理界面 问卷调查管理界面 问卷题目管理界面 用户登录界面 APP首页界面 公告信息界面 研究背景 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&…

组织病理学图像中的再识别|文献速递--基于多模态-半监督深度学习的病理学诊断与病灶分割

Title 题目 Re-identification from histopathology images 组织病理学图像中的再识别 01 文献速递介绍 在光学显微镜下评估苏木精-伊红&#xff08;H&E&#xff09;染色切片是肿瘤病理诊断中的标准程序。随着全片扫描仪的出现&#xff0c;玻片切片可以被数字化为所谓…

怎么在单片机裸机程序中移植EasyLogger?

1、介绍 EasyLogger 是一款超轻量级、高性能的C日志库&#xff0c;非常适合对资源敏感的软件项目。例如&#xff1a;IoT产品、可穿戴设备、智能家居等等。相比log4c、zlog这些知名的C日志库&#xff0c;EasyLogger的功能更加简单&#xff0c;提供给用户的接口更少&#xff0c;但…

肺腺癌预后新指标:全切片图像中三级淋巴结构密度的自动化量化|文献精析·24-10-09

小罗碎碎念 本期这篇文章&#xff0c;我去年分享过一次。当时发表在知乎上&#xff0c;没有标记参考文献&#xff0c;配图的清晰度也不够&#xff0c;并且分析的还不透彻&#xff0c;所以趁着国庆假期重新分析一下。 这篇文章的标题为《Computerized tertiary lymphoid structu…

基于springboot vue 校园失物招领平台的设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm springcloud等开发框架&#xff09; vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作☆☆☆ 精彩专栏推荐订阅☆☆☆☆…

【AIGC】OpenAI API在快速开发中的实践与应用:优化ChatGPT提示词Prompt加速工程

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;使用最新型号确保最佳实践利用最新模型进行高效任务处理为什么要选择最新模型&#xff1f;结论 &#x1f4af;指令与上下文的分隔最佳实践分隔指令和上下文的重要性使用符…

叉车毫米波雷达防撞技术,保护叉车作业安全

在叉车作业频繁的仓库与物流中心&#xff0c;安全隐患往往隐藏于细微之处&#xff0c;稍有不便可能引发重大事故。我们的叉车毫米波防撞系统方案&#xff0c;正是针对这一痛点而精心设计的创新之作。该系统通过集成的毫米波雷达技术&#xff0c;实现了对叉车周边环境的实时、精…

【动态规划】dp之斐波那契数列模型

学习编程就得循环渐进&#xff0c;扎实基础&#xff0c;勿在浮沙筑高台 循环渐进Forward-CSDN博客 目录 循环渐进Forward-CSDN博客 第N个泰波那契序数 思路&#xff1a; 代码实现&#xff1a; 三步问题 思路&#xff1a; 代码实现&#xff1a; 使用最小花费爬楼梯 思路…

C语言 | 第十三章 | 二维数组 冒泡排序 字符串指针 断点调试

P 120 数组应用案例 2023/1/29 一、应用案例 案例一&#xff1a;创建一个char类型的26个元素的数组&#xff0c;分别 放置’A’-Z‘。使用for循环访问所有元素并打印出来。提示&#xff1a;字符数据运算 ‘A’1 -> ‘B’ #include<stdio.h>void main(){/*创建一个c…

【优选算法之BFS】No.15--- 经典BFS解决FloodFill算法和解决最短路问题

文章目录 前言一、BFS解决FloodFill算法示例&#xff1a;1.1 图像渲染1.2 岛屿数量1.3 岛屿的最⼤⾯积1.4 被围绕的区域 二、BFS解决最短路问题2.1 迷宫中离⼊⼝最近的出⼝2.2 最⼩基因变化2.3 单词接⻰2.4 为⾼尔夫⽐赛砍树 前言 &#x1f467;个人主页&#xff1a;小沈YO. &a…

Linux高级编程_31_消息队列

文章目录 消息队列作用&#xff1a;特点&#xff1a;消息队列限制值&#xff1a;注意&#xff1a;命令&#xff1a;ftok函数作用&#xff1a;语法&#xff1a; msgget函数作用&#xff1a;语法&#xff1a; msgsnd函数作用&#xff1a;语法&#xff1a; msgrcv函数作用&#xf…

QT实现QInputDialog中文按钮

这是我记录Qt学习过程心得文章的第三篇&#xff0c;主要是为了方便QInputDialog输入框的使用&#xff0c;通过自定义的方式&#xff0c;按钮中文化&#xff0c;统一封装成一个函数&#xff0c;还是写在了Skysonya类里面。 实现代码&#xff1a; //中文按钮文本输入对话框 QSt…

【gRPC】1—gRPC是什么

gRPC是什么 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; &#x1f4d6;RPC专栏&#xff1a;https://b…

鸿蒙--播放器状态控制

各个页面共享同一个播放状态&#xff0c;而且可以互相控制&#xff0c;如果传递来传递去会非常的麻烦&#xff0c;但是他们都是Tabs组件内的&#xff0c;我们在index页面提供一个状态&#xff0c;在各个组件接收即可 创建两个子组件&#xff0c;一个是播放控制的子组件&#xf…

1. Oracle 安装报错——环境变量过长

文章目录 1. 报错详细信息2. 解决方案2.1 方案一&#xff1a;修改配置文件cvu_prereq.xml2.2 方案二&#xff1a;修改环境变量配置 1. 报错详细信息 安装 Oracle 过程中&#xff0c;在执行 “先决条件检查” 时报错&#xff1a; 报错内容&#xff1a; This test checks wheth…

【自然语言处理】(3) --RNN循环神经网络

文章目录 RNN循环神经网络一、传统神经网络的问题二、RNN的基本结构三、计算过程4. RNN的局限 总结 RNN循环神经网络 循环神经网络&#xff08;RNN&#xff0c;Recurrent Neural Network&#xff09;是一种用于处理序列数据的神经网络模型。其关键特性在于网络节点&#xff08…

现代数字信号处理I-P2概率论学习笔记

目录 学习视频链接&#xff1a; 1. 三要素及关系 2. 期望和方差的定义及基本性质 2.1 期望&#xff08;均值&#xff09;定义&#xff1a; 在实际工作中很难获得随机变量的分布或者概率密度&#xff0c;用矩描述随机变量 2.2 期望基本性质&#xff1a; 2.3 方差定义 2.…