SpringBoot实现oss文件的上传与下载
最近项目中需要通过OSS来实现文件的上传和下载以及根据oss文件(word模板)生成Word,特此记录,以便日后查阅。
一、相关概述
OSS对象存储
阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。OSS可用于图片、音视频、日志等海量文件的存储。各种终端设备、Web网站程序、移动应用可以直接向OSS写入或读取数据。
OSS相关概念
(1)Endpoint:外网访问oss服务器的域名
,通过该域名可以访问OSS服务的API,进行文件上传、下载等操作。
(2)Bucket:存储空间
,是存储对象的容器,所有存储对象都必须隶属于某个存储空间。
(3)Object:对象
,对象是 OSS 存储数据的基本单元,也被称为 OSS 的文件(可以是.png,.txt等任意文件)。
(4)AccessKey:访问密钥
,指的是访问身份验证中用到的 AccessKeyId 和 AccessKeySecret。
二、准备工作
1.开通OSS服务
开通阿里云的OSS服务,开通之后创建Bucket并设置AccessKey ID。
得到相关的配置信息:endPoint、accessKeyId、accessKeySecret、bucketName。
注册阿里云:
https://www.aliyun.com/?utm_content=se_1007692031
有账号的直接登录。
开通OSS:
https://oss.console.aliyun.com/?spm=5176.8466032.recommends.doss.28131450C6FqWR
如何创建Bucket和设置AccessKey ID?
答: 可以参考开通阿里云服务存储OSS中的介绍,介绍的挺详细的,这里就不在累赘,感谢该博主的分享。
2.创建SpringBoot项目
快捷创建链接地址:https://start.spring.io/
三、代码实现
1.实现oss文件上传与下载
官方文档:https://help.aliyun.com/document_detail/32009.html
1.1 添加必要依赖
<!-- web支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- OSS SDK 相关依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.6.0</version>
</dependency>
<!-- 文件上传 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- word导出-->
<!-- poi-tl是基于Apache POI的Word模板引擎。poi-tl依赖的是poi3.16版本 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.7.3</version>
</dependency>
<!-- 上面需要的依赖-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 对JSP的支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
application.properties:
#设置Tomcat端口号,默认8083
server.port=8085
#设置项目ContextPath 项目访问前缀
server.context-path=/
#设置Tomcat编码
server.tomcat.uri-encoding=UTF-8
#设置视图解析器路径
spring.mvc.view.prefix=/WEB-INF/views/
#设置视图解析器后缀
spring.mvc.view.suffix=.jsp
#配置文件上传的文件大小限制
spring.servlet.multipart.maxFileSize=300MB
spring.servlet.multipart.maxRequestSize=500MB
#静态资源路径
web.upload-path=D:/mimi/
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath\:/META-INF/resources/,classpath\:/resources/,classpath\:/static/,classpath\:/public/,file\:${web.upload-path}
1.2 创建OSS常量类
package com.example.ossdemo.common;
/**
* OSS 常量类
* @author Administrator
*
*/
public class OSSConstant {
//oss对外服务的访问域名
public static final String OSS_ENDPOINT = "http://oss-cn-shanghai.aliyuncs.com/";
//访问身份验证中用到的用户标识
public static final String OSS_ACCESSKEYID = "your AccessKeyId";
//用户用于加密签名字符串和oss用来验证签名字符串的 密钥
public static final String OSS_ACCESSKEYSECRET = "your AccessKeySecret";
//oss的存储空间
public static final String OSS_BUCKET = "cf-001";
//阿里云OSS文件地址
public static final String OSS_PIC_URL = "http://cf-001.oss-cn-shanghai.aliyuncs.com/";
}
1.3添加OSS业务接口OssService
package com.example.ossdemo.service;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface OssService {
/**
* 文件上传
* @param filepath
* @param inputstream
* @return
*/
public boolean uploadFile(String filepath, InputStream inputstream);
/**
* 下载oss文件
* @param request
* @param response
*/
public void downFile(HttpServletRequest request,HttpServletResponse response);
}
1.4 添加OSS业务接口OssService的实现类OssServiceImpl(含oss各种功能方法)
package com.example.ossdemo.service.impl;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.PutObjectResult;
import com.example.ossdemo.common.OSSConstant;
import com.example.ossdemo.service.OssService;
@Service("OssService")
public class OssServiceImpl implements OssService {
private String[] fileTypes = new String[]{
"gif", "jpg", "jpeg", "png", "bmp"};
/**
* 上传文件处理逻辑
*/
@Override
public boolean uploadFile(String filepath, InputStream inputstream) {
return upload(filepath, inputstream);
}
/**
* oss文件下载处理逻辑
*/
@Override
public void downFile(HttpServletRequest request, HttpServletResponse response) {
// oss文件地址
String oss_url = request.getParameter("url");
// 获取域名后面的内容
String oss_domain = OSSConstant.OSS_PIC_URL;
String file_name = oss_url.replace(oss_domain, "");
// 获取oss文件byte[]
byte[] oss_byte = getOssFileByteArray(file_name);
// 后缀名
String fileExt = oss_url.substring(oss_url.lastIndexOf(".") + 1).toLowerCase();
try {
// 清空response
response.reset();
// 设置response的Header
response.setHeader("Content-Disposition",
"attachment;filename=" + new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) + "." + fileExt);
// response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(oss_byte);// 以流的形式下载文件。
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 上传文件
*/
public boolean upload(String filepath, InputStream inputstream) {
boolean result = false;
// 初始化配置参数
String OSS_ENDPOINT = OSSConstant.OSS_ENDPOINT;
String OSS_ACCESSKEYID = OSSConstant.OSS_ACCESSKEYID;
String OSS_ACCESSKEYSECRET = OSSConstant.OSS_ACCESSKEYSECRET;
String OSS_BUCKET = OSSConstant.OSS_BUCKET;
OSSClient ossClient = null;
try {
if (filepath != null && !"".equals(filepath.trim())) {
// 创建ClientConfiguration实例,按照您的需要修改默认参数
ClientConfiguration conf = new ClientConfiguration();
// 开启支持CNAME选项
conf.setSupportCname(true);
ossClient = new OSSClient(OSS_ENDPOINT, OSS_ACCESSKEYID, OSS_ACCESSKEYSECRET, conf);
// 上传
ossClient.putObject(OSS_BUCKET, filepath, inputstream);
result = true;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件上传异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 列出oss bucket中的文件及目录
*
* @param dirname 目录名称,如: image/ , image/20201224/
*/
public List<Map<String,Object>> list_file(String dirname) {
// 初始化配置参数
String OSS_ENDPOINT = OSSConstant.OSS_ENDPOINT;
String OSS_ACCESSKEYID = OSSConstant.OSS_ACCESSKEYID;
String OSS_ACCESSKEYSECRET = OSSConstant.OSS_ACCESSKEYSECRET;
String OSS_BUCKET = OSSConstant.OSS_BUCKET;
List<Map<String,Object>> fileList = new ArrayList<Map<String,Object>>();
OSSClient ossClient = null;
try {
if (dirname != null && !"".equals(dirname.trim()) && dirname.endsWith("/")) {
// 创建ClientConfiguration实例,按照您的需要修改默认参数
ClientConfiguration conf = new ClientConfiguration();
// 开启支持CNAME选项
conf.setSupportCname(true);
ossClient = new OSSClient(OSS_ENDPOINT, OSS_ACCESSKEYID, OSS_ACCESSKEYSECRET, conf);
final int maxKeys = 200;
String nextMarker = null;
ObjectListing objectListing = null;
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(OSS_BUCKET);
listObjectsRequest.withMarker(nextMarker);
listObjectsRequest.withMaxKeys(maxKeys);
listObjectsRequest.withPrefix(dirname);
objectListing = ossClient.listObjects(listObjectsRequest);
List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (OSSObjectSummary s : sums) {
String key = s.getKey();
String lastmodifytime = sf.format(s.getLastModified());
System.out.println(key);
long size = s.getSize();
if (!key.equals(dirname)) {
Map<String,Object> file = new HashMap<String, Object>();
file.put("lastmodifytime",lastmodifytime);//最新修改时间
file.put("filesize",size);//文件尺寸
String sub_filepath = key.substring((key.indexOf(dirname) + dirname.length()), key.length());
int count = appearNumber(sub_filepath, "/");
if (count == 1 && sub_filepath.endsWith("/")) {
// 子目录
file.put("is_dir",true);//是否目录
boolean hasfile = check_has_file(sums, dirname + sub_filepath);
file.put("has_file",hasfile);//是否含有子文件
file.put("is_photo",false);//是否图片
file.put("filetype","");//文件类型
String filename = sub_filepath.