OSS前后端分离式上传文件,OSS前端直传

背景

以前我们一直采用:
后端转传 的方式进行文件上传 发现效率很低 且 后端服务器压力较大
现在我们优化成:
前端直传 后端提供token令牌 前端拿到令牌直接访问OSS上传文件效率提高了 且服务器压力也小了

准备工作

1:登录阿里云控制台创建RAM用户
在这里插入图片描述
在这里插入图片描述
及时截图或者复制 AccessKey ID 和 AccessKey Secret
这两项是OSS权限
在这里插入图片描述

这个STS角色访问权限 需要通过这个权限去获取token

在这里插入图片描述
创建角色
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建OSS存储桶

在这里插入图片描述
在这里插入图片描述
取名选择区域按提示完成创建
在这里插入图片描述

开放跨域请求

在这里插入图片描述
在这里插入图片描述

准备工作完毕

建个Spring Boot项目

引入依赖


<dependency><groupId>com.aliyun.ossgroupId><artifactId>aliyun-sdk-ossartifactId><version>3.10.2version>
dependency>

<dependency><groupId>javax.xml.bindgroupId><artifactId>jaxb-apiartifactId><version>2.3.1version>dependency><dependency><groupId>javax.activationgroupId><artifactId>activationartifactId><version>1.1.1version>dependency><dependency><groupId>org.glassfish.jaxbgroupId><artifactId>jaxb-runtimeartifactId><version>2.3.3version>dependency>

写个接口应该难不倒你

@RestController
@RequestMapping("/manager/auth")
public class AuthController {@Autowiredprivate OssService ossService;@GetMapping(value = "/oss/token")//这里的R是我自己封装的统一返回对象 你也可以直接返回JSON啥的public R ossToken() {return R.data(ossService.token());}
}
# 文件上传
OSS:# 区域endpoint: "https://oss-cn-xxxxx.aliyuncs.com"# 密钥accessKeyId: "xxxxxxxxxxxxxxxxxxxxxxxx"accessKeySecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"# roleArnroleArn: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"# 桶bucketName: "xxxxxxxxx"regionId: "cn-shanghai"version: "2015-04-01"
@Data
@Configuration
public class OSSParam {@Value("${OSS.endpoint}")private String endpoint;@Value("${OSS.accessKeyId}")private String accessKeyId;@Value("${OSS.accessKeySecret}")private String accessKeySecret;@Value("${OSS.roleArn}")private String roleArn;@Value("${OSS.bucketName}")private String bucketName;@Value("${OSS.regionId}")private String regionId;@Value("${OSS.version}")private String version;
}
public interface OssService {/*** 获取上传文件的token* @return*/AssumeRoleResponse token();/*** 批量获取图片连接** @param filePathList* @return*/Map<String, String> getUrlBatch(Collection<String> filePathList);
}
@Service
public class OssServiceImpl implements OssService {/*** 自定义的配置参数的类*/@Autowiredprivate OSSParam ossParam;@Overridepublic AssumeRoleResponse token() {//随便写 参考下列格式即可 不要有特殊符号String roleSessionName = "session_1001";//执行角色授权IClientProfile profile = DefaultProfile.getProfile(//cn-hangzhou 或者 cn-beijing 或者 cn-shanghai 这几个节点都可以 其他的好像不行ossParam.getRegionId(),//开通账号时下发的两个参数ossParam.getAccessKeyId(),ossParam.getAccessKeySecret());DefaultAcsClient client = new DefaultAcsClient(profile);final AssumeRoleRequest request = new AssumeRoleRequest();//version 这里是固定的 2015-04-01request.setVersion(ossParam.getVersion());//开通角色时 角色信息里的 arn 属性request.setRoleArn(ossParam.getRoleArn());request.setRoleSessionName(roleSessionName);//临时授权有效时间,从 900 到 3600 秒 测试的时候建议写时间给长一点,免得报错都不知道为啥request.setDurationSeconds(900L);try {final AssumeRoleResponse response = client.getAcsResponse(request);return response;} catch (ClientException e) {e.printStackTrace();return null;}}/*** 文件临时访问 URL 获取** @param filePathList 后端存储的文件路径*                     例如 : web/img/abc.jpg*                     其实就是你存储桶里面的文件夹路径*                     注意最前面不要带斜杠 例如这样 /web/img/abc.jpg 不要问我为什么 自己去试试就知道了* @return 文件夹链接的 key : value 集合 调用方可以直接通过 map.get(filePath) 直接获取对应的链接*/@Overridepublic Map<String, String> getUrlBatch(Collection<String> filePathList) {//这里 等于 Map resultMap = new HashMap<>(); 只是我引用了工具包看起来舒服一点Map<String, String> resultMap = Maps.newHashMap();if (CollectionUtils.isEmpty(filePathList)) {return resultMap;}//这个token可以用redis存起来过期了再重新生成,效率会高一点//过期时间保持一致 或者redis缓存时间稍微短一点,错开那种刚好过期的时间点就好了//比如 token 900秒(15分钟)到期,你就设置redis的key 720秒(12分钟)到期,完美错开AssumeRoleResponse token = token();// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(params.getStsEndpoint(),token.getCredentials().getAccessKeyId(),token.getCredentials().getAccessKeySecret(),token.getCredentials().getSecurityToken());//过期时间尽量短一点 1-3 分钟即可,//只要前端能够显示出来就行了 (时间太长,可能会被人恶意访问造成流量泄露,产生大量费用。切记!!!!)//以前小白的时候直接生成10年有效的链接。。。现在看起来是真的虎Long expirationTime = System.currentTimeMillis() + params.getStsEffectiveTime();Date expirationDate = new Date(expirationTime);filePathList.forEach(filePath -> {//生成GET请求链接URL url = ossClient.generatePresignedUrl(params.getStsBucketName(), filePath, expirationDate);resultMap.put(filePath, url.toString());});return resultMap;}
}

用postman点一下看看

在这里插入图片描述
返回一堆东西!说明功夫没白费

来到前端工作

本人是个写后端的 前端没怎么学,但只需要知道大概原理即可
首先去GitHub 下载两个 sdk 文件
在这里插入图片描述

再写个HTML试试水 (建个VUE项目太麻烦 索性就写个HTML玩玩儿)

DOCTYPE html>
<html><head><meta charset="utf-8"><title>title><form><input id="file" type="file" value="" onchange="getOssClient()" /><input id="upload" value="点击上传" type="button" onclick="uploadFile()" />form>head><body>body><script type="text/javascript" src="C:\xxx\xxx\xxx\dist\aliyun-oss-sdk.js">script><script type="text/javascript" src="C:\xxx\xxx\xxx\dist\aliyun-oss-sdk.min.js">script><script type="text/javascript">var params = {accessKeyId: "对应上一步接口返回的 {credentials.accessKeyId}",accessKeySecret: "对应上一步接口返回的 {credentials.accessKeySecret}",stsToken: "对应上一步接口返回的 {credentials.securityToken}",region: "你创建桶的区域 例如:oss-cn-chengdu",bucket: "你创建的桶名称"}function getOssClient() {return new OSS({...params})}function uploadFile() {let client = getOssClient();var file = document.getElementById('file').files;console.info(file[0].name);console.info(client);//这里是两个参数  var1 = 你的文件全路径(包括文件名), var2 文件原件var rep = client.put("/web_files/test/" + file[0].name, file[0])console.info(rep);}script>
html>

好了!试试看,选一个文件,就把这个js文件传上去看看
在这里插入图片描述
发现返回了貌似链接的东西 我们只需要把这个链接传给后端保存起来就OK了
在这里插入图片描述
再去控制台看看到底有没有
在这里插入图片描述

在这里插入图片描述

好了赶紧去点赞收藏吧


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部