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

黯然神伤888 2024-08-25 11:03:02 阅读 56

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

上传文件到oss的方式:

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

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

后端上传

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

添加maven依赖

<code> <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:

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

<code>@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-hangzhoucn-beijingcn-shanghaicn-qingdaocn-zhangjiakoucn-huhehaotecn-shenzhencn-chengducn-hongkongcn-hangzhou-internal

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

<title></title>

</head>

<body>

<div id="app">code>

<!-- HTML部分 -->

<input type="file" id="fileInput" accept="image/*" ref="fileInput" @change="uploadFile" />code>

</div>

</body>

<script src="js/jquery-1.10.2.min.js"></script>code>

<script src="js/vue.min.js"></script>code>

<script src="node_modules/ali-oss/dist/aliyun-oss-sdk.min.js"></script>code>

<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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。