前端、后端上传文件到OSS,简明记录

news2024/12/23 9:32:55

前端、后端上传文件到OSS,简明记录

上传文件到oss的方式:

**后端上传:**文件先要从页面上传到后端存起来,再通过后端发送到oss,然后后端将存起来的文件删除(当然可以不删)。

**前端上传:**文件通过前端页面直接上传到OSS服务器,不需要传到后端服务器,但是要先从后端获取上传OSS的凭证,然后再上传到OSS。

后端上传

后端上传的方式,官网有现成的sdk,非常简单,导入依赖后,对着代码传送你要上传的文件到后端即可

添加maven依赖

        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.15.1</version>
        </dependency>

复制下面代码到JUnit中执行了一下,更改对应的endpoint、bucketName等参数,即可执行文件上传到oss,不过对应的accessKey、accessKeySecret参数都存放在环境变量中,这也是阿里云推荐这么操作,为了安全起见以及代码与配置分离。当然你也可以直接在代码中或properties、yml文件中配置。

@Test
    public void testOSSUpload() throws com.aliyuncs.exceptions.ClientException {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-nanjing.aliyuncs.com";
        
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "othersitefiles";
        
        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
        String objectName = "exampledir/exampleobject.jpg";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            File file = new File("D:\\Bruce\\dog.jpg");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try (InputStream is = new FileInputStream(file)) {
                byte[] buffer = new byte[1024];
                int readCount;
                while ((readCount = is.read(buffer)) != -1) {
                    bos.write(buffer, 0, readCount);
                }
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bos.toByteArray()));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        }  finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

因为是在idea中执行的JUnit测试上传,所以环境变量需要再ide中配置。

image-20240401172119410

image-20240401172213302

如果是在idea中运行web项目测试,则可以在ide中配置环境变量,也可以在系统环境变量中进行配置,如果两者都设置了,则优先会从ide中获取配置。

而如果是发布以后的web项目,则就必须在系统环境变量中去设置。

image-20240401172655418

image-20240401172722147


前端上传:

既然要上传到oss,其实就不用上传后端,最好是由前端安全的把文件传到oss,这种操作最为合理。

这是后需要先到阿里云去配置账户与角色

image-20240401173106764

image-20240401173149755

image-20240401173239380

image-20240401173414993

在这里可以得到你新建账户的accessKeyaccessSecret,然后给这个用户添加权限

image-20240401173542192

image-20240402000609315

然后再新增角色

image-20240401173731574

image-20240401173745059

image-20240401173805942

image-20240401173849002

image-20240401173904834

image-20240401173926755

为角色也添加权限后,找到AEN的值,在代码中会用到

image-20240401174031115

后端代码:

service:

这里基本把参数都配置到环境变量中了

@Service("fileUploadOSSService")
public class FileUploadOSSServiceImpl implements FileUploadService {

    private Logger logger = LoggerFactory.getLogger(FileUploadOSSServiceImpl.class);

    @Override
    public R getToken(@CurrentUserPC UsersVO usersVO) {
        try {
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

            String region = System.getenv("REGION");
            String rolearn = System.getenv("ROLEARN");

            // 初始化默认profile,填入您的AK信息
            DefaultProfile profile = DefaultProfile.getProfile(
                    region, credentialsProvider.getCredentials().getAccessKeyId(), credentialsProvider.getCredentials().getSecretAccessKey());

            // 创建DefaultAcsClient实例并初始化
            IAcsClient client = new DefaultAcsClient(profile);

            // 创建AssumeRoleRequest请求对象
            AssumeRoleRequest request = new AssumeRoleRequest();

            request.setRoleArn(rolearn);
            request.setRoleSessionName("MySession");
            // 可选设置会话持续时间,默认为900秒
            request.setDurationSeconds(900L);

            // 发起请求并获取响应
            AssumeRoleResponse response = client.getAcsResponse(request);

            // 解析并打印临时凭证信息
            String accessKeyId = response.getCredentials().getAccessKeyId();
            String accessKeySecret = response.getCredentials().getAccessKeySecret();
            String securityToken = response.getCredentials().getSecurityToken();
            String endpoint = System.getenv("OSS_ENDPOINT");
            String bucket = System.getenv("BUCKET");

            System.out.println("临时AccessKeyId: " + accessKeyId);
            System.out.println("临时AccessKeySecret: " + accessKeySecret);
            System.out.println("临时SecurityToken: " + securityToken);

            OSSVO ossVO = new OSSVO();
            ossVO.setAccessKeyId(accessKeyId);
            ossVO.setAccessKeySecret(accessKeySecret);
            ossVO.setSecurityToken(securityToken);
            ossVO.setEndpoint(endpoint);
            ossVO.setExpiration(response.getCredentials().getExpiration());
            ossVO.setBucketName(bucket);
            ossVO.setRegion(region);

            ossVO.setFileName(RandomUtils.getUUID() + System.currentTimeMillis() + usersVO.getUid());

            return R.ok().put("data", ossVO);
        } catch (ClientException e) {
            e.printStackTrace();
            logger.error("获取token失败,com.aliyun.oss.ClientException:", e);
        } catch (ServerException e) {
            e.printStackTrace();
            logger.error("获取token失败,ClientException:", e);
        } catch (com.aliyuncs.exceptions.ClientException e) {
            e.printStackTrace();
            logger.error("获取token失败,com.aliyuncs.exceptions.ClientException:", e);
        }
        return R.error("获取token失败");
    }

}

image-20240402001642443

BUCKET为Bucket名称
image-20240402001824721

OSS_ACCESS_KEY_ID与OSS_ACCESS_KEY_SECRET则是刚才创建RAM用户的AccessKey ID与 Accesskey Secret

image-20240402002050534

OSS_ENDPOINT为Endpoint

image-20240402002306488

ROLEARN就是在角色那里的ARN值

image-20240402002923551

OSS_SESSION_TOKEN不用管,REGION为地区,一般就是Endpoint中的地区,按理我这里应该对应是cn-nanjing,但是查了下对照表,cn-nanjing的对应REGION应该是cn-hangzhou,所以我这里填的是cn-hangzhou

image-20240402002532426

目前阿里云在中国大陆地区的regionId主要有:

  • cn-hangzhou
  • cn-beijing
  • cn-shanghai
  • cn-qingdao
  • cn-zhangjiakou
  • cn-huhehaote
  • cn-shenzhen
  • cn-chengdu
  • cn-hongkong
  • cn-hangzhou-internal

根据阿里云的官方文档,南京节点(Nanjing)并未单独作为一个regionId列出,而是作为华东2(Hangzhou)的一部分。所以,如果在南京节点使用OSS服务,应该使用cn-hangzhou作为regionId。

controller:
@Api("文件上传")
@RestController
@RequestMapping("/pcApi/fileUpload")
public class FileUploadController {

    @Autowired
    @Qualifier("fileUploadOSSService")
    private FileUploadService fileUploadOSSService;

    @ApiOperation("获取OSS token")
    @PostMapping("/getOSSToken")
    public R getOSSToken(@CurrentUserPC UsersVO usersVO) {
        return fileUploadOSSService.getToken(usersVO);
    }

}

前端代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
			<!-- HTML部分 -->
			<input type="file" id="fileInput" accept="image/*" ref="fileInput" @change="uploadFile" />
		</div>
	</body>
	<script src="js/jquery-1.10.2.min.js"></script>
	<script src="js/vue.min.js"></script>
	<script src="node_modules/ali-oss/dist/aliyun-oss-sdk.min.js"></script>
	<script>
		var app = new Vue({
			el: "#app",
			data: {

			},
			created() {

			},
			methods: {
				uploadFile(event) {
					const file = event.target.files[0];
					// 获取文件后缀名
					var fileExtension = file.name.substring(file.name.lastIndexOf('.') + 1);
				
					// 转换为小写以便不区分大小写比较
					fileExtension = fileExtension.toLowerCase();
					
					debugger;
					// 确保文件已选择
					if (file) {
						// 上传文件的逻辑
						const token =
							"eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7InVpZCI6MiwidXNlcm5hbWUiOiJ6aGFuZ2RpIiwidHlwZSI6MX19._ADwwEioEnyV7L_xqPjWZgeR_13ow5uDU01Togtr90I"; // 根据实际情况从存储中获取token
						// 前端请求后端获取临时凭证
						$.ajax({
							url: "http://localhost:8099/pcApi/fileUpload/getOSSToken",
							dataType: "json",
							method: "POST",
							headers: {
								"token": token
							},
							success: function(data) {
								
								if (data.code == 0) {
									console.log(data.data);
									const credentials = data.data;

									// 初始化OSS客户端
									const client = new OSS({
										region: credentials.region,
										accessKeyId: credentials.accessKeyId,
										accessKeySecret: credentials.accessKeySecret,
										bucket: credentials.bucketName,
										stsToken: credentials.securityToken,
										endpoint: credentials.endpoint, // 使用STS提供的Endpoint
										refreshSTSToken: this.getNewSTSToken,
										refreshSTSTokenInterval: 300000, // 设置STS Token刷新间隔,单位是毫秒,默认值是300000(即5分钟)
									});

									// 开始上传文件
									try {
										const result = client.put('weiqingview/'+credentials.fileName + '.' + fileExtension, file);
										debugger;
										console.log('Upload successful:', result);
										
									} catch (error) {
										console.error('Failed to upload file:', error);
									}
								}
							}
						});
					}
				},

				// 在初始化OSS客户端之后定义一个函数用来获取新的STS Token
				getNewSTSToken(callback) {
					$.ajax({
						url: "http://localhost:8099/pcApi/fileUpload/getOSSToken",
						dataType: "json",
						method: "POST",
						headers: {
							"token": token // 这里的token应该来自实际的用户认证信息或者存储中的有效token
						},
						success: function(data) {
							if (data.code === 0) {
								const newCredentials = data.data;
								callback(null, {
									accessKeyId: newCredentials.accessKeyId,
									accessKeySecret: newCredentials.accessKeySecret,
									securityToken: newCredentials.securityToken
								});
							} else {
								// 处理错误,例如重新获取或其他逻辑
								console.error('Failed to fetch new STS Token:', data.message);
								callback(new Error(data.message));
							}
						},
						error: function(xhr, status, err) {
							// 请求失败处理
							console.error('Error while fetching new STS Token:', err);
							callback(err);
						}
					});
				}
			}
		});
	</script>
</html>

对照着需要引入jquery与vue,而aliyun-oss-sdk.min.js需要通过npm 或yarn安装一下,或者引入cdn也行

npm install ali-oss --save
# 或者
yarn add ali-oss

运行

image-20240402003730282

image-20240402003846053

发现图片已经上传到oss

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

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

相关文章

win11安装WSL UbuntuTLS

win11安装WSL WSL 简介WSL 1 VS WSL 2先决要求安装方法一键安装通过「控制面板」安装 WSL 基本命令Linux发行版安装Ubuntu初始化相关设置root用户密码网络工具安装安装1panel面板指导 WSl可视化工具问题总结WSL更新命令错误Ubuntu 启动初始化错误未解决问题 WSL 简介 Windows …

4-Linux实用操作

1. 各类小技巧&#xff08;快捷键&#xff09; 1.1 ctrl c 强制停止 Linux 某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键 ctrl c 命令输入错误&#xff0c;也可以通过快捷键 ctrl c&#xff0c;退出当前输入&#xff0c;重新输入 1.2 ctrl …

P6维护:Oracle P6服务性能优化

前言 本文将介绍如何对ORACLE Primavera P6 EPPM软件进行性能调优&#xff0c;考虑到P6主要采用JAVA语言编制&#xff0c;且其使用的是Weblogic Server应用服务器部署P6各项服务器&#xff0c;其性能优化的原理便是基于其JVM特征参数进行设置 方法一&#xff1a;修改配置文件…

NoSQL之 Redis配置

目录 关系数据库与非关系型数据库 关系型数据库&#xff1a; ●非关系型数据库 关系型数据库和非关系型数据库区别&#xff1a; &#xff08;1&#xff09;数据存储方式不同 &#xff08;2&#xff09;扩展方式不同 对事务性的支持不同 非关系型数据库产生背景 Redis简介…

利用Node.js实现拉勾网数据爬取

引言 拉勾网作为中国领先的互联网招聘平台&#xff0c;汇集了丰富的职位信息&#xff0c;对于求职者和人力资源专业人士来说是一个宝贵的数据源。通过编写网络爬虫程序&#xff0c;我们可以自动化地收集这些信息&#xff0c;为求职决策和市场研究提供数据支持。Node.js以其非阻…

Intel FPGA (2):线性序列机

Intel FPGA (2)&#xff1a;线性序列机 前提摘要 个人说明&#xff1a; 限于时间紧迫以及作者水平有限&#xff0c;本文错误、疏漏之处恐不在少数&#xff0c;恳请读者批评指正。意见请留言或者发送邮件至&#xff1a;“Email:noahpanzzzgmail.com”。本博客的工程文件均存放在…

预处理指令——一些比较少见的概念

前言&#xff1a;预处理是我们的c语言源代码成为可执行程序的第一个步骤。而宏和预处理指令都是在这个阶段完成。本节内容就是关于宏和预处理指令相关知识点的解析。 目录 宏 预定义符号 #define定义常量 #define定义符号 #define定义宏 带副作用的宏参数 宏的替换规则…

【C语言基础】:自定义类型(二) -->联合和枚举

文章目录 一、联合体1.1 联合体类型的声明1.2 联合体的特点1.3 相同成员的结构体和联合体对比1.4 联合体大小的计算1.5 联合体练习 二、枚举类型2.1 枚举类型的声明2.2 枚举的优点 书山有路勤为径&#xff0c;学海无涯苦作舟。 创作不易&#xff0c;宝子们&#xff01;如果这篇…

嵌入式介绍

1、嵌入式系统学习的三条路线 单片机入门HAL 单片机核心/RTOS Liuxc 2.学习嵌入式的三条路线的优缺点 2.1.单片机入门(HAL) 简单、快速&#xff0c;实际上工作中涉及单片机编程时&#xff0c;也提倡使用HAL库。 对于学习来说&#xff0c;HAL封装了很多技术细节&#xff0c…

使用虚拟引擎为AR体验提供动力

Powering AR Experiences with Unreal Engine ​​​​​​​ 目录 1. 虚拟引擎概述 2. 虚拟引擎如何为AR体验提供动力 3. 虚拟引擎中AR体验的组成部分是什么&#xff1f; 4. 使用虚拟引擎创建AR体验 5. 虚拟引擎中AR的优化提示 6. 将互动性融入AR与虚拟引擎 7. 在AR中…

Python反爬案例——验证码的识别

验证码的识别 使用打码平台识别验证码 利用打码平台可以轻松识别各种各样的验证码&#xff0c;图形验证码、滑动验证码、点选验证码和逻辑推理验证码。打码平台提供了一系列API&#xff0c;只需要向API上传验证码图片&#xff0c;它便会返回对应的识别结果。 使用超级鹰平台…

Qt 实现的万能采集库( 屏幕/相机/扬声器/麦克风采集)

【写在前面】 之前应公司需要&#xff0c;给公司写过一整套直播的库( 推拉流&#xff0c;编解码)&#xff0c;类似于 libobs。 结果后来因为没有相关项目&#xff0c;便停止开发&维护了。 不过里面很多有用的组件&#xff0c;然后也挺好用的&#xff0c;遂开源出来一部分。…

软件测试(测试用例详解)(三)

1. 测试用例的概念 测试用例&#xff08;Test Case&#xff09;是为了实施测试而向被测试的系统提供的一组集合。 测试环境操作步骤测试数据预取结果 测试用例的评价标准&#xff1a; 用例表达清楚&#xff0c;无二义性。。用例可操作性强。用例的输入与输出明确。一条用例只有…

怎么在UE游戏中加入原生振动效果

我是做振动触感的。人类的五感“视听嗅味触”&#xff0c;其中的“触”就是触觉&#xff0c;是指皮肤、毛发与物体接触时的感觉。触感可以带来更加逼真的沉浸式体验。但也许过于司空见惯&#xff0c;也是习以为常&#xff0c;很多人漠视了触感的价值。大家对触感的认知还远远不…

skywalking idea中启动调试报错Output path is shared between the same module error

报错信息 简单描述&#xff1a;就是多个moudle一样用了一样的输出路径&#xff0c;这样容易造成冲突 Output path is shared between the same module error 参考&#xff1a;scala - Output path is shared between the same module error - Stack Overflow 解决方法&…

VScode使用Prettier格式化代码

1、安装Prettier插件 2、扩展设置 3、设置.prettierrc.json配置文件路径 4、.prettierrc 配置文件 .prettierrc.json 是 Prettier 格式化工具的配置文件&#xff0c;用于指定代码格式化的规则和风格。下面是一些可能的配置选项&#xff0c;请自行选择&#xff1a; {"prin…

spring boot自动配置原理-怎样回答这个问题

首先我们说一下自动配置的概念。 自动配置&#xff1a;遵循约定大约配置的原则&#xff0c;在boot程序启动后&#xff0c;起步依赖中的一些bean对象会自动注入到ioc容器 例子 程序引入spring-boot-starter-web 起步依赖&#xff0c;启动后&#xff0c;会自动往ioc容器中注入…

一文了解微带天线

微带天线介绍 微带天线的结构一般由介质基板、辐射体及接地板构成。介质基板的厚度远小于波长&#xff0c;基板底部的金属薄层与接地板相接&#xff0c;正面则通过 光刻工艺 制作具有特定形状的金属薄层作为辐射体。 辐射片的形状根据要求可进行多种变化。微波集成技术和新型制…

高频小信号放大器概述

高频放大器与低频&#xff08;音频&#xff09;放大器的主要区别是&#xff1a;工作频率范围和所需通过的频带宽度都有所不同。其采用的负载也不相同。 低频放大器的工作频率低&#xff0c;但工作频带宽度很宽&#xff0c;所以负载采用无调谐负载&#xff0c;例如电阻、有铁心…

Docker容器监控之CAdvisor+InfluxDB+Granfana

介绍&#xff1a;CAdvisor监控收集InfluxDB存储数据Granfana展示图表 目录 1、新建3件套组合的docker-compose.yml 2、查看三个服务容器是否启动 3、浏览cAdvisor收集服务&#xff0c;http://ip:8080/ 4、浏览influxdb存储服务&#xff0c;http://ip:8083/ 5、浏览grafan…