文件上传流程:
创建阿里云OSS(对象存储服务)的bucket
登录阿里云,并完成实名认证,地址:https://www.aliyun.com/.
可以通过搜索,进入以下页面:
点击立即使用后:
点击试用后,就开通了相关服务,然后在产品中搜索“OSS”,点击管理平台:
点击“Bucket列表”,进行创建:
代码
创建成功后再次进入bucket列表,通过帮助文档进入到SDK,选择Java:
也可以使用以下文件上传代码示例:
代码思路:
配置文件中 (application-dev.xml) 添加OSS的配置项,可以通过配置属性类(AliOssProperties)加载并封装这些属性值,然后通过OssConfiguration创建AliOssProperties,其中OssConfiguration在项目启动时就能调用aliOssUtil方法,把该对象创建出来后,交给spring容器进行管理(通过@Bean实现,@ConditionalOnMissingBean保证整个spring容器里面只有一个AliOssUtil对象),因此可以在对应的Controller类中,通过@Autowired获取到AliOssUtil,实现文件上传。
package com.sky.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;/*** 文件上传** @param bytes* @param objectName* @return*/public String upload(byte[] bytes, String objectName) {// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {// 创建PutObject请求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} 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();}}//文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder = new StringBuilder("https://");stringBuilder.append(bucketName).append(".").append(endpoint).append("/").append(objectName);log.info("文件上传到:{}", stringBuilder.toString());return stringBuilder.toString();}
}
相关配置项的设置:
- 设置配置属性类:
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;}
- 项目配置文件设置application.xml:
server:port: 8080spring:profiles:active: devmain:allow-circular-references: truedatasource:druid:driver-class-name: ${sky.datasource.driver-class-name}url: jdbc:mysql://${sky.datasource.host}:${sky.datasource.port}/${sky.datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: ${sky.datasource.username}password: ${sky.datasource.password}mybatis:#mapper配置文件mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.sky.entityconfiguration:#开启驼峰命名map-underscore-to-camel-case: truelogging:level:com:sky:mapper: debugservice: infocontroller: infosky:jwt:# 设置jwt签名加密时使用的秘钥admin-secret-key: itcast# 设置jwt过期时间admin-ttl: 7200000# 设置前端传递过来的令牌名称admin-token-name: token# 添加阿里云文件存储服务相关配置alioss:endpoint: ${sky.alioss.endpoint}access-key-id: ${sky.alioss.access-key-id}access-key-secret: ${sky.alioss.access-key-secret}bucket-name: ${sky.alioss.bucket-name}
这里使用变量的方式添加阿里云对象存储服务的相关属性值,以便适应开发(dev)和产品(prod)两种环境,当前使用的环境为dev,于是在application-dev.xml中设置相关属性值,如:
sky:datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: xxxxusername: rootpassword: xxxxalioss:endpoint: oss-cn-hangzhou.aliyuncs.comaccess-key-id: xxxxaccess-key-secret: xxxxbucket-name: xxxx
添加OSS配置类
package com.sky.config;import com.sky.properties.AliOssProperties;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** ClassName: OssConfig* PackageName: com.sky.config* Description: 配置类,用于创建AliOssUtil对象** @Author Xiyan Zhong* @Create 2023/12/19 下午4:35* @Version 1.0*/
@Configuration
@Slf4j
public class OssConfiguration {@Bean@ConditionalOnMissingBeanpublic AliOssUtil aliOssUtil(AliOssProperties aliOssProperties) {log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
}
相应的controller代码:
package com.sky.controller.admin;import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.UUID;/*** ClassName: CommonController* PackageName: com.sky.controller.admin* Description:通用上传接口** @Author Xiyan Zhong* @Create 2023/12/19 下午2:46* @Version 1.0*/@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {// 通过Autowired注解注入依赖@Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* @param file* @return*/@PostMapping("/upload")@ApiOperation("文件上传")// 参数名要与前端请求时的参数保持一致public Result<String> upload(MultipartFile file){log.info("文件上传:{}",file);try {// 获取原始文件名String originalFileName = file.getOriginalFilename();// 截取原始文件名的后缀String extension = originalFileName.substring(originalFileName.lastIndexOf("."));// 构造新文件名称String objectName = UUID.randomUUID().toString() + extension;// 第一个参数:文件对象转成的字节数组;第二个参数:文件上传到OSS中对应的名称,通过UUID+后缀生成,避免文件重名,导致文件覆盖。// filePath表示文件的请求路径String filePath = aliOssUtil.upload(file.getBytes(),objectName);return Result.success(filePath);}catch (IOException e){log.error("文件上传失败:{}",e);}return Result.error("文件上传失败");}
}