概述
- 笔者也不知道该怎么概述,在下面代码中主要就是几个参数比较难以搞懂,搞懂了参数就不难使用。那么开始吧!
Maven地址
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.16.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
必要参数
accessKeyId
- accessKeyId 是在登录阿里云官网时需要创建的,谁交给你这个开发任务那么就问谁去要。假设对方不知道,就要问对方要购买阿里云OSS服务的账号密码,然后在去控制台查看,具体查看方法可以百度。
accessKeySecret
- accessKeySecret 也是在登录阿里云官网时需要创建的,获取方法同上!
bucket
- Bucket 是在购买 OSS 服务的后要创建的,在哪里创建自行百度。
endPoint
- endPoint 是在购买 OSS 服务的后要创建的,在哪里创建自行百度。在下面图片的两个标记中,在点击确定按钮之前需要把这个两个参数保存好,虽然后期也可以查看,但是比较麻烦。
OSS配置类
- 笔者是把以上参数配置在 Springboot 的 yml 配置文件中,记得在保存的endPoint前加上https。以下配置仅供参考
## 阿里云配置
aliyunoss:
accessKeyId: LTAI5t8LBSMKX2R8ZLtn****
accessKeySecret: ekwm3JDe9wUbzuPLA8MF5f8tmT****
bucket: blog****pig
endPoint: https://oss-cn-beijing.aliyuncs.com
@Data
@Configuration
@ConfigurationProperties(prefix = "aliyunoss")
public class ALiYunOSSProperties {
private String accessKeyId;
private String accessKeySecret;
private String bucket;
private String endPoint;
}
具体实现代码
顶级接口
/**
* @author unknown
* @since 2023/08/12 13:18
*/
public interface BlogFileService {
/**
* <P>上传图片</P>>
*
* @param file 文件对象
* @return
*/
String uploadPictureFile(MultipartFile file) throws ClientException, IOException;
/**
* <P>下载文件</P>
*
* @param uri 图片完整路径
* @param request
* @param response
*/
InputStream downloadPictureFile(String uri, HttpServletRequest request, HttpServletResponse response);
/**
* <P>删除图片</P>
* @param url 图片完整路径
*/
void deletePictureFile(String url);
}
OSS实现类
/**
* @author unknown
* @since 2023/08/12 13:30
*/
@Slf4j
@Service
public class AliYunOSSFileImpl implements BlogFileService {
// Spring中读取配置文件的方法
@Value("aliyunoss.accessKeyId")
private String accessKeyId;
@Value("aliyunoss.accessKeySecret")
private String accessKeySecret;
@Value("aliyunoss.bucket")
private String bucket;
@Value("aliyunoss.endPoint")
private String endPoint;
@Autowired
private ALiYunOSSProperties aLiYunOSSProperties;
/**
* <P>阿里云OSS图片上传</P>
*
* @param file 文件对象
* @return 图片URL
* @throws IOException ClientException
* @see <a href="https://help.aliyun.com/zh/oss/developer-reference/oss-java-configure-access-credentials?spm=a2c4g.11186623.0.0.506cb417OuUTJk#8c51f4c0f0v92"> 请认真阅读官方文档-开发参考
*/
@Override
public String uploadPictureFile(MultipartFile file){
// 获取文件名
String originalFilename = file.getOriginalFilename();
// 获取配置文件参数
String accessKeyId = aLiYunOSSProperties.getAccessKeyId();
String accessKeySecret = aLiYunOSSProperties.getAccessKeySecret();
String endPoint = aLiYunOSSProperties.getEndPoint();
String bucket = aLiYunOSSProperties.getBucket();
// 访问密钥配置访问凭证
CredentialsProvider credentialsProviderCode = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endPoint, credentialsProviderCode);
try {
// 上传图片
ossClient.putObject(bucket, originalFilename, new ByteArrayInputStream(file.getBytes()));
// 获取图片URL
Date expiration = new Date(System.currentTimeMillis() + 3600 * 24 * 365 * 15 * 1000L);
return ossClient.generatePresignedUrl(bucket, originalFilename, expiration).toString();
} catch (OSSException oe) {
log.error("Caught an OSSException, which means your request made it to OSS, but was rejected with an error response for some reason.");
log.error("Error Message:" + oe.getErrorMessage());
log.error("Error Code:" + oe.getErrorCode());
log.error("Request ID:" + oe.getRequestId());
log.error("Host ID:" + oe.getHostId());
throw new BlogRuntimeException(ResultCode.PHOTO_UPLOAD_FAILED, oe.getMessage());
} catch (com.aliyun.oss.ClientException ce) {
log.error("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.");
log.error("Error Message:" + ce.getMessage());
throw new BlogRuntimeException(ResultCode.PHOTO_UPLOAD_FAILED, ce.getMessage());
}catch (IOException ioException){
throw new BlogRuntimeException(ResultCode.PHOTO_UPLOAD_FAILED, ioException.getMessage());
} finally {
// 关闭OSSClient。
ossClient.shutdown();
}
}
/**
* <P>阿里云OSS图片下载</P>
*
* @param url 图片完整路径,在数据库存储的路径,如果丢在浏览器可以直接访问,那么就可以正常使用
* @param request request
* @param response response
* @return InputStream
*/
@Override
public InputStream downloadPictureFile(String url, HttpServletRequest request, HttpServletResponse response) {
// 获取配置文件参数
String accessKeyId = aLiYunOSSProperties.getAccessKeyId();
String accessKeySecret = aLiYunOSSProperties.getAccessKeySecret();
String endPoint = aLiYunOSSProperties.getEndPoint();
String bucket = aLiYunOSSProperties.getBucket();
// 访问密钥配置访问凭证
CredentialsProvider credentialsProviderCode = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
OSS ossClient = new OSSClientBuilder().build(endPoint, credentialsProviderCode);
// 切割图片上传的url,获取上传时的文件名称,这一定很重要,你上传的文件是什么名字,那么就要用什么名字作为Key来访问
String fileName = url.substring(url.indexOf("/", 8) + 1, url.indexOf("?"));
try {
OSSObject ossObject = ossClient.getObject(new GetObjectRequest(bucket, fileName));
InputStream objectContent = ossObject.getObjectContent();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = objectContent.read(buffer)) > -1) {
outputStream.write(buffer, 0, len);
}
// 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
outputStream.flush();
outputStream.close();
objectContent.close();
return new ByteArrayInputStream(outputStream.toByteArray());
} catch (OSSException oe) {
log.error("Caught an OSSException, which means your request made it to OSS, but was rejected with an error response for some reason.");
log.error("Error Message:" + oe.getErrorMessage());
log.error("Error Code:" + oe.getErrorCode());
log.error("Request ID:" + oe.getRequestId());
log.error("Host ID:" + oe.getHostId());
throw new BlogRuntimeException(ResultCode.FILE_DOES_NOT_EXIST);
} catch (ClientException ce) {
log.error("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.");
log.error("Error Message:" + ce.getMessage());
throw new BlogRuntimeException(ResultCode.FILE_DOES_NOT_EXIST);
} catch (IOException e) {
log.error("AliYunOssServiceImpl downloadFile", e);
throw new BlogRuntimeException(ResultCode.FILE_DOES_NOT_EXIST);
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
/**
* <P>图片删除</P>
* @param url 图片完整路径,在数据库存储的路径,如果丢在浏览器可以直接访问,那么就可以正常使用
*/
@Override
public void deletePictureFile(String url) {
// 获取配置文件参数
String accessKeyId = aLiYunOSSProperties.getAccessKeyId();
String accessKeySecret = aLiYunOSSProperties.getAccessKeySecret();
String endPoint = aLiYunOSSProperties.getEndPoint();
String bucket = aLiYunOSSProperties.getBucket();
// 访问密钥配置访问凭证
CredentialsProvider credentialsProviderCode = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
OSS ossClient = new OSSClientBuilder().build(endPoint, credentialsProviderCode);
// 切割图片上传的url,获取上传时的文件名称,这一定很重要,你上传的文件是什么名字,那么就要用什么名字作为Key来访问
String fileName = url.substring(url.indexOf("/", 8) + 1, url.indexOf("?"));
ossClient.deleteObject(bucket, fileName);
ossClient.shutdown();
}
}
Controller层
/**
* @author unknown
* @since 2023/08/12 13:43
*/
@Slf4j
@RestController
@RequestMapping("/blog/version-1.0/file")
public class FileController {
@Autowired
private BlogFileService aLiYunOSSFile;
/**
* <P>图片上传</P>
*
* @param file 图片对象
* @return 图片URL
* @throws ClientException 阿里云OSS异常
*/
@PostMapping("/uploadPicture")
public Result<String> uploadPicture(MultipartFile file) throws ClientException, IOException {
log.info("FileController uploadPicture Request param: {}", file);
String picture = aLiYunOSSFile.uploadPictureFile(file);
log.info("FileController uploadPicture Response PictureURL: {}", picture);
return ResultBuilder.successResult(picture);
}
/**
* <P>删除图片</P>
* @param url 图片URL
* @return Result
*/
@DeleteMapping("/deletePicture")
public Result<String> deletePicture(@RequestParam String url){
log.info("FileController uploadPicture Request param: {}", url);
aLiYunOSSFile.deletePictureFile(url);
return ResultBuilder.successResult();
}
/**
* <P>图片下载到本地</P>
*
* @param url 图片地址
* @param request
* @param response
* @return 输出流
*/
@GetMapping(value = "/downloadPicture", produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE, MediaType.APPLICATION_JSON_VALUE})
public Result<String> downloadPicture(@RequestParam String url, HttpServletRequest request, HttpServletResponse response){
log.info("FileController downloadPicture Request param: {}", url);
InputStream inputStream = null;
BufferedOutputStream outputStream = null;
// 切割url获取上传时的文件名称
String fileName = url.substring(url.indexOf("/", 8) + 1, url.indexOf("?"));
try {
inputStream = aLiYunOSSFile.downloadPictureFile(url, request, response);
response.reset();
response.setHeader("Content-disposition", "attachment;filename=" + setFileDownloadHeader(request, fileName));
response.setContentType("application/octet-stream;charset=UTF-8");
outputStream = new BufferedOutputStream(response.getOutputStream());
if (inputStream != null) {
int len;
while ((len = inputStream.read()) != -1) {
outputStream.write(len);
outputStream.flush();
}
}
} catch (Exception e) {
log.error("FileController downloadFile error", e);
} finally {
if (Objects.nonNull(inputStream)) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (Objects.nonNull(outputStream)) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ResultBuilder.successResult();
}
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
final String agent = request.getHeader("USER-AGENT");
String filename = fileName;
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
filename = new String(fileName.getBytes(), "ISO8859-1");
} else if (agent.contains("Chrome")) {
// google浏览器
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
}
return filename;
}
}
Tips
- 对读者的一些小建议
- 读者任务时间不紧迫,请结合官网文档进行查看和Debug本代码。
- 时间紧迫,请直接粘贴复制即用。
- 还有什么问题可以给笔者发邮件,599303650@qq.com