前端、后端上传文件到OSS,简明记录
前端、后端上传文件到OSS,简明记录
上传文件到oss的方式:
**后端上传:**文件先要从页面上传到后端存起来,再通过后端发送到oss,然后后端将存起来的文件删除(当然可以不删)。
**前端上传:**文件通过前端页面直接上传到OSS服务器,不需要传到后端服务器,但是要先从后端获取上传OSS的凭证,然后再上传到OSS。
后端上传
后端上传的方式,官网有现成的sdk,非常简单,导入依赖后,对着代码传送你要上传的文件到后端即可
添加maven依赖
com.aliyun.oss aliyun-sdk-oss 3.15.1
复制下面代码到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中配置。
如果是在idea中运行web项目测试,则可以在ide中配置环境变量,也可以在系统环境变量中进行配置,如果两者都设置了,则优先会从ide中获取配置。
而如果是发布以后的web项目,则就必须在系统环境变量中去设置。
前端上传:
既然要上传到oss,其实就不用上传后端,最好是由前端安全的把文件传到oss,这种操作最为合理。
这是后需要先到阿里云去配置账户与角色
在这里可以得到你新建账户的accessKey与accessSecret,然后给这个用户添加权限
然后再新增角色
为角色也添加权限后,找到AEN的值,在代码中会用到
后端代码:
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失败"); } }
BUCKET为Bucket名称
OSS_ACCESS_KEY_ID与OSS_ACCESS_KEY_SECRET则是刚才创建RAM用户的AccessKey ID与 Accesskey Secret
OSS_ENDPOINT为Endpoint
ROLEARN就是在角色那里的ARN值
OSS_SESSION_TOKEN不用管,REGION为地区,一般就是Endpoint中的地区,按理我这里应该对应是cn-nanjing,但是查了下对照表,cn-nanjing的对应REGION应该是cn-hangzhou,所以我这里填的是cn-hangzhou
目前阿里云在中国大陆地区的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); } }
前端代码:
对照着需要引入jquery与vue,而aliyun-oss-sdk.min.js需要通过npm 或yarn安装一下,或者引入cdn也行
npm install ali-oss --save # 或者 yarn add ali-oss
运行
发现图片已经上传到oss