三种方式(oss、本地、minio)图片的上传下载

一、OSS

1、前期准备

1.1 注册阿里云账号,开启对象存储oss功能,创建一个bucket(百度教程多的是,跟着创建一个就行,创建时注意存储类型是标准存储,读写权限是公共读)

有的在创建桶时读写属性是私有,不能设置为公共,先设置为私有,后面再改就可以。

 2、后端准备

2.1引入依赖 
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version>
</dependency>
2.2:在application.yml中配置一些必要的属性,并写一个类读取出来(我是这样使用的,将某些特定的数据都写到application.yml文件中,方便更改,当然你也可以直接将他写在类的代码中,只不过找起来可能麻烦点 
bookstore:alioss:endpoint: xxxxx #外网访问的地域节点access-key-id: xxxxxx #访问阿里云api的秘钥access-key-secret: xxxxxxx #访问阿里云api的秘钥bucket-name: xxxxxxxx #bucket-name//写在application.yml文件中,这些数据在阿里云中可以找到,秘钥在自己的账号主页里创建生成,地域节点和bucket-name都在创建好bucket后查看
2.3 OssUtil是一个用于处理阿里云对象存储服务(Object Storage Service, OSS)的工具类,它利用了Spring框架的一些特性来实现配置属性的注入和初始化
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Data@Componentpublic class OssUtil implements InitializingBean {@Value("${aliyun.oss.file.endpoint}")private String endpoint;@Value("${aliyun.oss.file.keyid}")private String keyId;@Value("${aliyun.oss.file.keysecret}")private String keySecret;@Value("${aliyun.oss.file.bucketname}")private String bucketName;public static String END_POINT;public static String ACCESS_KEY_ID;public static String ACCESS_KEY_SECRET;public static String BUCKET_NAME;@Overridepublic void afterPropertiesSet() throws Exception {END_POINT = endpoint;ACCESS_KEY_ID = keyId;ACCESS_KEY_SECRET = keySecret;BUCKET_NAME = bucketName;}}

 2.4,创建一个接口

import org.springframework.web.multipart.MultipartFile;public interface OssService {/*上传图片到Oss*/String uploadFileAvatar(MultipartFile file);}
 2.5 OssServiceImpl类是一个服务类,它封装了与阿里云OSS交互的逻辑,其主要作用是处理文件(特别是图片)上传到阿里云对象存储服务(Object Storage Service, OSS)的逻辑。
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.wedu.common.utils.OssUtil;
import com.wedu.modules.dev.service.OssService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;@Service
public class OssServiceImpl implements OssService {@Overridepublic String uploadFileAvatar(MultipartFile file) {/*** 上传图片到oss** @param file 文件对象* @return*/if (file == null || file.isEmpty()) {return "文件为空,请选择文件后再上传。";}// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。String endpoint = OssUtil.END_POINT;// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。String accessKeyId = OssUtil.ACCESS_KEY_ID;String accessKeySecret = OssUtil.ACCESS_KEY_SECRET;String bucketName = OssUtil.BUCKET_NAME;try {// 获取文件名称String realName = file.getOriginalFilename();// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。InputStream inputStream = file.getInputStream();// 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。ossClient.putObject(bucketName, realName, inputStream);// 关闭OSSClient。ossClient.shutdown();String url = "https://" + bucketName + "." + endpoint + "/" + realName;return url;} catch (Exception e) {e.printStackTrace();return null;}}}
 2.6 Spring MVC的控制器方法,它定义了一个处理文件上传的HTTP POST请求的逻辑。
 /*** oss上传文件* @param file* @return*/@PostMapping("/upload")public R uploadFile(MultipartFile file) {String url = ossService.uploadFileAvatar(file);return R.ok().put("url",url);}

3、前端代码 

 <el-form-item label="设备图片"><!-- action 必选参数,上传的地址  headers设置上传的请求头部  show-file-list	是否显示已上传文件列表on-success	文件上传成功时的钩子  before-upload	上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。--><el-uploadclass="avatar-uploader":action= "uploadUrl":headers= "tokenInfo":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload"><img v-if="imageUrl" :src="imageUrl" class="avatar"><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></el-form-item>data () {return {imageUrl:'',//oss// uploadUrl: this.$http.adornUrl('/dev/fileoss/upload'),//本地上传接口// uploadUrl: this.$http.adornUrl('/dev/fileoss/uploadLocal'),//miniouploadUrl: this.$http.adornUrl('/dev/fileoss/minIOUpload'),tokenInfo: {'token': this.$cookie.get('token')},//上传成功后的钩子handleAvatarSuccess(res, file) {//将上传成功后的urlthis.dataForm.image = res.url;this.imageUrl = URL.createObjectURL(file.raw);},beforeAvatarUpload(file) {const isJPG = file.type === 'image/jpeg';const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG) {this.$message.error('上传头像图片只能是 JPG 格式!');}if (!isLt2M) {this.$message.error('上传头像图片大小不能超过 2MB!');}return isJPG && isLt2M;},

 图片展示

 <el-table-column prop="image" header-align="center" align="center" label="设备图片"><template slot-scope="scope"><img v-if="scope.row.image":src=" scope.row.image"style="width: 50px; height: 50px;" class="avatar"></template></el-table-column>

二、Minio

前期的安装准备参考这位博主的MinIO安装与启动【windows】_minio启动-CSDN博客, minio跟oss都是上传图片存储在第三方,前端代码没什么区别,后端代码不同点就是连接的配置不同。

导入依赖

<!-- MinIO --><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.2</version></dependency>

 没有像oss一样将连接信息写在yml里,直接所以普代码都写在控制层。

 //minIO 文件上传  直接返回图片路径@PostMapping("/minIOUpload")public R upload(MultipartFile file) throws IOException {// 设置 MinIO 连接信息 这里使用API端口 9000 而不是9001String endpoint = "http://192.168.255.1:9000";String accessKey = "你自己的账户名";String secretKey = "密码";String bucketName = "桶的名称";String bucketUrl = "http://192.168.255.1:9000/" + bucketName; // MinIO bucket URL// 获取当前时间戳String flag = System.currentTimeMillis() + " ";// 获取原始文件名(就是你上传的文件本身的名字)String originalFilename = file.getOriginalFilename();// 生成新的文件名(时间戳+原始文件名) 避免文件名相同被覆盖String fileName = flag + originalFilename;// 拼接完整的图片访问路径 URLString url = bucketUrl + "/" + fileName;try {// 创建 MinioClient 实例MinioClient minioClient = new MinioClient.Builder().endpoint(endpoint).credentials(accessKey, secretKey).build();// 构建文件上传相关信息PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(file.getInputStream(), file.getSize(), -1)//application/octet-stream 告诉浏览器这是一个附件,浏览器会直接进行下载,而不是预览.contentType(("application/octet-stream")).build();// 将文件上传到 MinIO 服务器minioClient.putObject(args);}catch (Exception e) {throw new ServerException("文件上传异常: " + e.getMessage(), e);}return R.ok().put("url", url);}

三、本地

本地代码如下:

 /*** 本地上传* @param file* @return*/@PostMapping("/uploadLocal")public R uploadFileLocal(MultipartFile file) {//获取当前时间戳String flag = System.currentTimeMillis() + " ";//获取原始文件名(就是你上传的文件本身的名字)String fileName = file.getOriginalFilename();try {//如果没有file文件夹,在项目根目录创建一个file文件夹if (!FileUtil.isDirectory(filePath)) {FileUtil.mkdir(filePath);}//文件存储形式:时间戳+文件名String destFileName =filePath + flag + fileName;// FileUtil.writeBytes(file.getBytes(), filePath + flag + fileName);File destFile = new File(destFileName);destFile.getParentFile();file.transferTo(destFile);Thread.sleep((1L));} catch (Exception e) {System.err.println(fileName + "--文件上传失败");}return R.ok().put("url", flag);}//本地下载@GetMapping("/{flag}")public void picturePath(@PathVariable String flag, HttpServletResponse response) {//用于向客户端写入数据的输出流OutputStream os;//存储文件名的列表。List<String> fileNames = FileUtil.listFileNames(filePath);//存储匹配标志的文件名。//使用Java 8的Stream API,从fileNames列表中筛选出包含flag的文件名。如果找到匹配项,则使用findAny().orElse("")获取匹配的文件名,否则返回空字符串。String picture = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");try {//如果picture不为空(即找到了匹配的文件名)if (StrUtil.isNotEmpty(picture)) {response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(picture, "UTF-8"));//响应的内容类型为application/octet-stream,确保浏览器不会尝试打开文件response.setContentType(("application/octet-stream"));//声明了一个字节数组bytes,用于存储文件的二进制内容byte[] bytes = FileUtil.readBytes(filePath + picture);os = response.getOutputStream();//将字节数组写入输出流,发送给客户端os.write(bytes);os.flush();os.close();}} catch (Exception e) {System.out.println("文件下载失败");}}

注意:前端代码需要改变一下,不然上传的图片是看不了的,回显的方法通过之前的前端代码是不会调用这和方法。需要在前端拼接一下url。这样就能展示了。

<el-table-column prop="image" header-align="center" align="center" label="设备图片"><template slot-scope="scope"><img v-if="scope.row.image":src="'http://localhost:8080/wedu/dev/fileoss/'+ scope.row.image"style="width: 50px; height: 50px;" class="avatar"> </template></el-table-column>

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

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

相关文章

Z2400032基于Java+Mysql+SSM的校园在线点餐系统的设计与实现 代码 论文

在线点餐系统 1.项目描述2. 技术栈3. 项目结构后端前端 4. 功能模块5. 项目实现步骤注意事项 6.界面展示7.源码获取 1.项目描述 本项目旨在开发一个校园在线点餐系统&#xff0c;通过前后端分离的方式&#xff0c;为在校学生提供便捷的餐厅点餐服务&#xff0c;同时方便餐厅和…

【前端】理解 JavaScript 中 typeof 操作符的独特行为

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;typeof 操作符的基本使用&#x1f4af;为什么 typeof 数组是 "object"&#xff1f;&#x1f4af;为什么 typeof {} 返回 "object"&#xff1f;&…

Github提交Pull Request教程 Git基础扫盲(零基础易懂)

1 PR是什么&#xff1f; PR&#xff0c;全称Pull Request&#xff08;拉取请求&#xff09;&#xff0c;是一种非常重要的协作机制&#xff0c;它是 Git 和 GitHub 等代码托管平台中常见的功能&#xff0c;被广泛用于参与社区贡献&#xff0c;从而促进项目的发展。 PR的整个过…

C/C++ 数据结构与算法【线性表】 顺序表+链表详细解析【日常学习,考研必备】带图+详细代码

1&#xff09;线性表的定义 线性表&#xff08;List&#xff09;&#xff1a;零个或多个数据元素的有限序列。 线性表的数据集合为{a1,a2,…,an}&#xff0c;假设每个元素的类型均为DataType。其中&#xff0c;除第一个元素a1外&#xff0c;每一个元素有且只有一个直接前驱元素…

浏览器的数据六种存储方法比较 :LocalStorage vs. IndexedDB vs. Cookies vs. OPFS vs. WASM-SQLite

在构建该 Web 应用程序&#xff0c;并且希望将数据存储在用户浏览器中。也许您只需要存储一些小标志&#xff0c;或者甚至需要一个成熟的数据库。 我们构建的 Web 应用程序类型发生了显着变化。在网络发展的早期&#xff0c;我们提供静态 html 文件。然后我们提供动态渲染的 h…

【C++boost::asio网络编程】有关异步读写api的笔记

异步读写api 异步写操作async_write_someasync_send 异步读操作async_read_someasync_receive 定义一个Session类&#xff0c;主要是为了服务端专门为客户端服务创建的管理类 class Session { public:Session(std::shared_ptr<asio::ip::tcp::socket> socket);void Conn…

芯片测试-RF中的S参数,return loss, VSWR,反射系数,插入损耗,隔离度等

RF中的S参数&#xff0c;return loss, VSWR&#xff0c;反射系数&#xff0c;插入损耗&#xff0c;隔离度 &#x1f4a2;S参数&#x1f4a2;&#x1f4a2;S11与return loss&#xff0c;VSWR&#xff0c;反射系数&#x1f4a2;&#x1f4a2;S21&#xff0c;插入损耗和增益&#…

2024年Java面试八股文大全(附答案版)

很多人会问Java面试八股文有必要背吗&#xff1f; 我的回答是&#xff1a;很有必要。你可以讨厌这模式&#xff0c;但你一定要去背&#xff0c;因为不背你就进不了大厂。 国内的互联网面试&#xff0c;恐怕是现存的、最接近科举考试的制度。 而且&#xff0c;我国的八股文确…

我不是挂王-用python实现燕双鹰小游戏

一.准备工作 1.前言提要 作为程序员在浩瀚的数字宇宙中&#xff0c;常常感觉现实世界是一台精密运作的虚拟机&#xff0c;其底层的物理逻辑如同铁律般难以撼动。然而我们拥有在虚拟世界中自由驰骋、创造无限可能的独特力量。突发奇我想用Python写出燕双鹰的小游戏,这样想想就很…

Python语法基础(七)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们今天的这篇文章&#xff0c;主要和大家讲一下函数重写的问题。 首先&#xff0c;我们要知道的是&#xff0c;函数重写是有前提条件的&#xff0c;那就是继承。 自定义函数…

NaviveUI框架的使用 ——安装与引入(图标安装与引入)

文章目录 概述安装直接引入引入图标样式库 概述 &#x1f349;Naive UI 是一个轻量、现代化且易于使用的 Vue 3 UI 组件库&#xff0c;它提供了一组简洁、易用且功能强大的组件&#xff0c;旨在为开发者提供更高效的开发体验&#xff0c;特别是对于构建现代化的 web 应用程序。…

神经网络入门实战:(九)分类问题 → 神经网络模型搭建模版和训练四步曲

(一) 神经网络模型搭建官方文档 每一层基本都有权重和偏置&#xff0c;可以仔细看官方文档。 pytorch 官网的库&#xff1a;torch.nn — PyTorch 2.5 documentation Containers库&#xff1a;用来搭建神经网络框架&#xff08;包含所有的神经网络的框架&#xff09;&#xff1b…

以AI算力助推转型升级,暴雨亮相CCF中国存储大会

2024年11月29日-12月1日&#xff0c;CCF中国存储大会&#xff08;CCF ChinaStorage 2024&#xff09;在广州市长隆国际会展中心召开。本次会议以“存力、算力、智力”为主题&#xff0c;由中国计算机学会&#xff08;CCF&#xff09;主办&#xff0c;中山大学计算机学院、CCF信…

Java中的“抽象类“详解

1.抽象类的定义 在面向对象的概念中,所有的对象都是通过,类来描述的,但是反过来,不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描述一个具体的对象,这样的类就是抽象类 抽象类的概念是比较抽象的,比如现在有一个"父类"是"动物类",继…

NVR监测软件EasyNVR多个NVR同时管理:录播主机的5条常见问题与解决办法

视频监控广泛应用于城市治安、交通管理、商业安保及家庭监控等领域。在使用EasyNVR平台管理多个NVR设备时&#xff0c;尤其是涉及到海康录播主机的场景中&#xff0c;使用者可能会遇到一些常见问题。本文将探讨海康录播主机的五个常见问题及其解决办法。 1、海康录播主机的5条常…

多级缓存设计实践

缓存是什么&#xff1f; 缓存技术是一种用于加速数据访问的优化策略。它通过将频繁访问的数据存储在高速存储介质&#xff08;如内存&#xff09;中&#xff0c;减少对慢速存储设备&#xff08;如硬盘或远程服务器&#xff09;的访问次数&#xff0c;从而提升系统的响应速度和…

Linux网络编程之---多线程实现并发服务器

下面我们来使用tcp集合多线程实现并发服务器 一.服务端 #include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h>typedef struct sockinfo {char ip[16];unsigne…

Web API基本认知

作用和分类 作用&#xff1a;就是使用JS去操作html和浏览器 分类&#xff1a;DOM&#xff08;文档对象模型&#xff09;、BOM&#xff08;浏览器对象模型&#xff09; 什么是DOM DOM&#xff08;Document Object Model ——文档对象模型&#xff09;是用来呈现以及与任意 HTM…

《Python基础》之Numpy库

目录 简介 一、创建数组 1、根据列表创建数组 2、创建全0数组 3、创建全1数组 4、创建单位矩阵 5、创建随机数数组 二、查看数组的属性 三、 数组的操作 1、索引和切片 2、变形 3、拼接 &#xff08;1&#xff09;、vstack() 纵向拼接 &#xff08;2&#xff09;、hs…

人工智能-卷积神经网络(学习向)

一.概述&#xff1b; 卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;是一种专门用于处理具有类似网格结构的数据&#xff08;如图像&#xff09;的深度学习模型。 主要用于处理机器视觉任务。 主要功能&#xff1b; 1.图像分类 2.目标检测 3.图像分割…