SpringBoot实现oss文件的上传与下载
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.substring(0, sub_filepath.length() - 1);
file.put("filename",filename);//文件名
fileList.add(file);
} else if (count == 0) { // 文件
file.put("is_dir",false);//是否目录
file.put("has_file",false);//是否含有子文件
String fileExt = key.substring(key.lastIndexOf(".") + 1).toLowerCase();
file.put("is_photo",Arrays.<String>asList(fileTypes).contains(fileExt));//是否图片
file.put("fileExt",fileExt);//文件类型
file.put("filename",sub_filepath);//文件名
fileList.add(file);
}
}
}
nextMarker = objectListing.getNextMarker();
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("获取文件列表异常");
} finally {
if (ossClient != null) {
// 关闭client
ossClient.shutdown();
}
}
return fileList;
}
/**
* public int indexOf(int ch, int fromIndex) 返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索
*
* @param srcText
* @param findText
* @return
*/
public static int appearNumber(String srcText, String findText) {
int count = 0;
int index = 0;
while ((index = srcText.indexOf(findText, index)) != -1) {
index = index + findText.length();
count++;
}
return count;
}
private boolean check_has_file(List<OSSObjectSummary> sums, String dirname) {
boolean result = false;
for (OSSObjectSummary s : sums) {
String path = s.getKey();
if (!dirname.equals(path) && path.startsWith(dirname)) {
result = true;
break;
}
}
return result;
}
/**
* 检验oss bucket 某个目录下是否存在文件
*
* @param dirname 目录名称,如: image/ , image/20201224/
*/
public boolean check_is_empty(String dirname) {
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 (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);
// 列举Object
ObjectListing objectListing = ossClient.listObjects(OSS_BUCKET, dirname);
List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
if (sums.size() > 0) {
result = true;
}
System.out.println("检索目录:" + dirname + " 是否存在:" + result);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("校验文件异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 检验oss bucket中是否存在目录
*
* @param dirname 目录名称,如: image/ , image/20201224/
*/
public boolean check_dir_exist(String dirname) {
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 (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);
// Object是否存在
result = ossClient.doesObjectExist(OSS_BUCKET, dirname.trim());
System.out.println("检索目录:" + dirname + " 是否存在:" + result);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件校验异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 在oss bucket中创建目录
*
* @param dirname 目录名称,如: image/ , image/20201224/
*/
public boolean create_dir(String dirname) {
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 (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);
PutObjectResult r = ossClient.putObject(OSS_BUCKET, dirname, new ByteArrayInputStream(new byte[0]));
result = true;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("目录创建异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 上传文件
*/
public boolean upload(String filepath, FileInputStream fileinputstream) {
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, fileinputstream);
result = true;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件上传异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 上传文件
*/
public boolean upload(String filepath, byte[] filecontent) {
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, new ByteArrayInputStream(filecontent));
result = true;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件上传异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 上传文件
*/
public boolean upload(String filepath, ByteArrayInputStream bytestream) {
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, bytestream);
result = true;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件上传异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 删除bucket中的文件
*/
public boolean delete(String filename) {
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 (filename != null && !"".equals(filename.trim())) {
filename = filename.trim();
String key = filename.substring(OSS_BUCKET.length() - 1, filename.length());
// 创建ClientConfiguration实例,按照您的需要修改默认参数
ClientConfiguration conf = new ClientConfiguration();
// 开启支持CNAME选项
conf.setSupportCname(true);
ossClient = new OSSClient(OSS_ENDPOINT, OSS_ACCESSKEYID, OSS_ACCESSKEYSECRET, conf);
// 删除
ossClient.deleteObject(OSS_BUCKET, key);
result = true;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件删除异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 获取oss文件byte[]
*/
public byte[] getOssFileByteArray(String filepath) {
byte[] result = null;
// 初始化配置参数
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);
// 上传
OSSObject ossObj = ossClient.getObject(OSS_BUCKET, filepath);
if (ossObj != null) {
InputStream is = ossObj.getObjectContent();
result = InputStreamToByteArray(is);
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("文件下载异常");
} finally {
// 关闭client
ossClient.shutdown();
}
return result;
}
/**
* 1.图片转为字节数组
* 图片到程序FileInputStream
* 程序到数组 ByteArrayOutputStream
*/
public static byte[] InputStreamToByteArray(InputStream is) {
// 1.创建源与目的的
byte[] dest = null;// 在字节数组输出的时候是不需要源的。
// 2.选择流,选择文件输入流
ByteArrayOutputStream os = null;// 新增方法
try {
os = new ByteArrayOutputStream();
// 3.操作,读文件
byte[] flush = new byte[1024 * 10];// 10k,创建读取数据时的缓冲,每次读取的字节个数。
int len = -1;// 接受长度;
while ((len = is.read(flush)) != -1) {
// 表示当还没有到文件的末尾时
// 字符数组-->字符串,即是解码。
os.write(flush, 0, len);// 将文件内容写出字节数组
}
os.flush();
return os.toByteArray();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 4.释放资源
try {
if (is != null) {// 表示当文打开时,才需要通知操作系统关闭
is.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
/**
* 2.将字节数组还原为文件
* 字节数组到程序ByteArrayInputStream
* 程序到文件。FileOutputStream
*/
public static void byteArrayToFile(byte[] src, String FilePath) {
//1.创建源
File dest = new File(FilePath);//该文件是不存在的,会在相应的路径下创建
// 2.选择流
FileOutputStream os = null;
ByteArrayInputStream is = null;
try {
//3.操作
os = new FileOutputStream(dest);
is = new ByteArrayInputStream(src);
//将内容写出
byte[] flush = new byte[1024 * 10];//创建读取数据时的缓冲,每次读取的字节个数。
int len = -1;//接受长度;
while ((len = is.read(flush)) != -1) {
//表示当还没有到文件的末尾时
//字符数组-->字符串,即是解码。
os.write(flush, 0, len);//
}
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//4.释放资源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
1.5添加OSSFileUploadController,实现oss文件上传、下载
package com.example.ossdemo.controller;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import com.example.ossdemo.common.OSSConstant;
import com.example.ossdemo.service.OssService;
/**
* oss文件上传、下载
*
* @author Administrator
*
*/
@RequestMapping("/oss_file")
@RestController
public class OSSFileUploadController {
@Autowired
private OssService ossService;
//定义允许上传的文件扩展名
private static HashMap<String, String> extMap = new HashMap<String, String>();
static {
extMap.put("image", "gif,jpg,jpeg,png,bmp");
extMap.put("flash", "swf,flv");
extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb");
extMap.put("file", "pdf,doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2,java,php,exe,gif,jpg,jpeg,png,bmp");
}
//最大文件大小 100M
long maxSize = 104857600;
//最大文件大小 10M
long maxImages = 10485760;
/**
* 进入oss文件上传、下载页面
* @return
*/
@RequestMapping("/index")
public ModelAndView toIndex(){
return new ModelAndView("oss/index");
}
/**
* 图片上传
* @param file
* @return
*/
@RequestMapping(value = "/upload_img", method = RequestMethod.POST)
public Map<String,Object> uploadImg(@RequestParam("file") MultipartFile file) {
Map<String,Object> result = new HashedMap<String, Object>();
//允许上传的文件扩展名
String fileTypes = "gif,jpg,jpeg,png,bmp";
String fileName = file.getOriginalFilename();
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
long fileSize = file.getSize();
try {
if (fileSize > maxImages) {
result.put("code", "fail");
result.put("msg", "上传图片大小超过限制" + (maxImages / 1024) + "KB");
result.put("error", 1);// 富文本框图片上传,失败返回值
} else if (!Arrays.<String>asList(fileTypes.split(",")).contains(fileExt)) {
result.put("code", "fail");
result.put("msg", "图片格式有误,\n只允许" + fileTypes + "格式。");
result.put("error", 1);// 富文本框图片上传,失败返回值
} else {
// 生成新的文件名
String newfilename = "image/";
Date now = new Date();
SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
newfilename += date.format(now) + "/";
SimpleDateFormat time = new SimpleDateFormat("HHmmssSSS");
newfilename += time.format(now);
newfilename += "_" + new Random().nextInt(1000) + "." + fileExt;
ossService.uploadFile(newfilename, file.getInputStream());
//返回文件访问路径
String url = OSSConstant.OSS_PIC_URL + newfilename;
result.put("code", "success");
result.put("url", url);
result.put("error", 0);// 富文本框图片上传,成功返回值
}
} catch (Exception e) {
result.put("code", "fail");
result.put("msg", "系统异常");
e.printStackTrace();
}
return result;
}
/**
* 普通文件上传
* @param file
* @return
*/
@RequestMapping(value = "/upload_attachment", method = RequestMethod.POST)
public Map<String,Object> uploadAttachment(@RequestParam("file") MultipartFile file,HttpServletRequest request) {
Map<String,Object> result = new HashedMap<String, Object>();
//允许上传的文件扩展名
String fileTypes = "pdf,doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2,java,php,exe,gif,jpg,jpeg,png,bmp";
String fileName = file.getOriginalFilename();
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
long fileSize = file.getSize();
try {
if (fileSize > maxImages) {
result.put("code", "fail");
result.put("msg", "上传文件大小超过限制" + (maxImages / 1024) + "KB");
} else if (!Arrays.<String>asList(fileTypes.split(","))
.contains(fileExt)) {
result.put("code", "fail");
result.put("msg", "文件格式有误,\n只允许" + fileTypes + "格式。");
} else {
//生成新的文件名
String newfilename = "file/";
Date now = new Date();
SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
newfilename += date.format(now) + "/";
SimpleDateFormat time = new SimpleDateFormat("HHmmssSSS");
newfilename += time.format(now);
newfilename += "_" + new Random().nextInt(1000) + "." + fileExt;
ossService.uploadFile(newfilename, file.getInputStream());
//返回文件访问路径
String url = OSSConstant.OSS_PIC_URL + newfilename;
result.put("code", "success");
result.put("url", url);
}
} catch (Exception e) {
result.put("code", "fail");
result.put("msg", "系统异常");
e.printStackTrace();
}
return result;
}
/**
* oss文件下载
*/
@RequestMapping(value = "/downFile", method = {RequestMethod.GET})
public void downFile(HttpServletRequest request,HttpServletResponse response){
ossService.downFile(request, response);
}
}
1.6 创建jsp文件,调用上传、下载方法
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<head>
<!-- easyUI -->
<link rel="stylesheet" href="<%=basePath %>/js/jquery-easyui-1.7.0/themes/default/easyui.css">
<link rel="stylesheet" href="<%=basePath %>/js/jquery-easyui-1.7.0/themes/icon.css">
<link rel="stylesheet" href="<%=basePath %>/css/common.css">
<script type="text/javascript" src="<%=basePath %>/js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="<%=basePath %>/js/jquery-easyui-1.7.0/jquery.easyui.min.js"></script>
<script type="text/javascript" src="<%=basePath %>/js/jquery-easyui-1.7.0/locale/easyui-lang-zh_CN.js"></script>
<!-- layer 弹出层 -->
<script type="text/javascript" src="<%=basePath %>/js/layer/layer.js"></script>
<link rel="stylesheet" href="<%=basePath %>/js/layui-v2.5.6/css/layui.css">
<style>
.m1{
margin-left: 10px;
}
.s1{
font-weight: bold;
color:#1e9fff;
}
.m2{
margin-bottom: 10px;
}
</style>
</head>
<body class="easyui-layout">
<h1 class="m1">OSS文件上传、下载:</h1>
<div class="easyui-tabs" style="width:700px;height:250px;margin: 10px 0 0 10px;">
<div title="图片上传" style="padding:10px">
<div class="m2" style="margin-top: 30px;font-weight: bold;">图片上传</div>
<div class="m2" style="margin-top: 30px;">
<img alt="" src="" id="img_url">
<input type="hidden" id="img_url2" value="">
</div>
<a href="#" class="easyui-linkbutton" id="imgButton">图片上传</a>
</div>
<div title="普通文件上传" style="padding:10px">
<div class="m2" style="margin-top: 30px;font-weight: bold;">普通文件上传</div>
<div class="m2" style="margin-top: 30px;">
文件地址:<input type="text" id="url" class="easyui-textbox" style="width:600px;" value="" readonly="readonly">
</div>
<a href="#" class="easyui-linkbutton" id="fileButton">文件上传</a>
</div>
<div title="文件下载" style="padding:10px">
<div class="m2" style="margin-top: 30px;font-weight: bold;">oss文件下载</div>
<div class="m2" style="margin-top: 30px;">
文件地址:<input type="text" id="url3" class="easyui-textbox" style="width:600px;" value="http://xiaofang-001.oss-cn-shanghai.aliyuncs.com/file/20201216/093915477_23.docx" readonly="readonly">
</div>
<a href="#" class="easyui-linkbutton" onclick="downloadFile()">文件下载</a>
</div>
</div>
<script src="<%=basePath %>/js/layui-v2.5.6/layui.js" charset="utf-8"></script>
<script type="text/javascript">
layui.use('upload', function(){
var $ = layui.jquery,upload = layui.upload;
var loading;
//图片上传
upload.render({
elem: '#imgButton'
,url: '/oss_file/upload_img' //改成您自己的上传接口
,accept: 'file' //普通文件 //指定允许上传时校验的文件类型,可选值有:images(图片)、file(所有文件)、video(视频)、audio(音频)
,acceptMime:'image/*'//规定打开文件选择框时,筛选出的文件类型,值为用逗号隔开的 MIME 类型列表。如:acceptMime: 'image/*'(只显示图片文件)acceptMime: 'image/jpg, image/png'(只显示 jpg 和 png 文件)
,before: function(obj){
loading = layer.msg("上传中", {
icon: 16,
time: 10000000,
shade: 0.3
});
},
done: function(res){
if (res.code == "success"){
layer.close(loading);
layer.msg('上传成功');
console.log(res.url);
$("#img_url").attr("src",res.url)
$("#img_url2").val(res.url)
}
},error: function(res){
//请求异常回调
console.log(res)
}
});
//普通文件上传
upload.render({
elem: '#fileButton'
,url: '/oss_file/upload_attachment' //改成您自己的上传接口
,accept: 'file' //普通文件 //指定允许上传时校验的文件类型,可选值有:images(图片)、file(所有文件)、video(视频)、audio(音频)
//,exts: 'docx|doc' //只允许上传word文件
,before: function(obj){
loading = layer.msg("上传中", {
icon: 16,
time: 10000000,
shade: 0.3
});
},
done: function(res){
if (res.code == "success"){
layer.close(loading);
layer.msg('上传成功');
console.log(res.url);
$("#url").val(res.url)
}
}
});
});
function downloadFile(){
window.location.href='/oss_file/downFile?oss_url='+$("#url3").val();
}
</script>
</body>
</html>
2.实现Word生成
需求:将Word模板上传到oss中并入库,之后根据这个模板生成相应的销售合同Word,并把这个Word上传到oss,返回相应的oss文件地址并入库,以便之后使用(下载)。
2.1 编写word模板,并上传
Word模板上传见上面。 入库省略不讲。
word模板:
讲解下如何根据 oss文件生成Word并上传oss。
2.2添加导出word业务接口ExportWordService
package com.example.ossdemo.service;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public interface ExportWordService {
/**
* 导出订单合同信息
* @param request
*/
public Map<String,Object> exportOrderContractInfo(HttpServletRequest request) throws Exception;
}
2.3 ExportWordService的实现类
package com.example.ossdemo.service.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ClassUtils;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import com.example.ossdemo.common.OSSConstant;
import com.example.ossdemo.service.ExportWordService;
import com.example.ossdemo.service.OssService;
import com.example.ossdemo.utils.MoneyUtils;
@Service("ExportWordService")
public class ExportWordServiceImpl implements ExportWordService{
@Autowired
private OssService ossService;
@Autowired
private OssServiceImpl ossServiceImpl;
/**
* 导出订单合同word
*/
@Override
public Map<String, Object> exportOrderContractInfo(HttpServletRequest request) throws Exception {
Map<String, Object> result = new HashMap<String, Object>();
//模拟数据请求,组装必要数据
Map<String, Object> data = new HashMap<String, Object>();
//导出word
exportWordOrderInfo(data);
result.put("code", "success");
return result;
}
/**
* 生成订单合同word
* @param request
* @param response
* @throws IOException
*/
public void exportWordOrderInfo(Map<String,Object> data){
Map<String, Object> params = new HashMap<>();
DecimalFormat df = new DecimalFormat("######0.00");
Calendar now = Calendar.getInstance();
double money = 0;//总金额
//模拟数据请求,组装表格列表数据
List<Map<String,Object>> detailList=new ArrayList<Map<String,Object>>();
for (int i = 0; i < 6; i++) {
Map<String,Object> detailMap = new HashMap<String, Object>();
detailMap.put("index", i+1);//序号
detailMap.put("title", "商品"+i);//商品名称
detailMap.put("product_description", "套");//商品规格
detailMap.put("buy_num", 3+i);//销售数量
detailMap.put("saleprice", 100+i);//销售价格
double saleprice=Double.valueOf(String.valueOf(100+i));
Integer buy_num=Integer.valueOf(String.valueOf(3+i));
String buy_price=df.format(saleprice*buy_num);
detailMap.put("buy_price", buy_price);//单个商品总价格
money=money+Double.valueOf(buy_price);
detailList.add(detailMap);
}
//总金额
String order_money=String.valueOf(money);
//金额中文大写
String money_total = MoneyUtils.change(money);
// 渲染文本{{}}
//渲染表格
HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
Configure config = Configure.newBuilder().bind("detailList", policy).build();
String basePath=ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static/template/";//本地
String oss_url="http://xiaofang-001.oss-cn-shanghai.aliyuncs.com/file/20201217/130652163_419.docx";//模板地址(存储在oss上的模板文件地址)
//word模板地址
String resource=getResourceName(oss_url, basePath);//将oss上传文件地址 还原成 目标文件
XWPFTemplate template = XWPFTemplate.compile(resource, config).render(
new HashMap<String, Object>() {{
put("detailList", detailList);
put("order_number", "2356346346645");
put("y", now.get(Calendar.YEAR));//当前年
put("m", (now.get(Calendar.MONTH) + 1));//当前月
put("d", now.get(Calendar.DAY_OF_MONTH));//当前日
put("order_money",order_money);//总金额
put("money_total",money_total);//金额中文大写
}}
);
String newFilePath=basePath+getNewFilePath1(resource);
try {
File newFile = new File(basePath, getNewFilePath1(resource));
FileOutputStream out = new FileOutputStream(newFile);
template.write(out);
out.flush();
out.close();
template.close();
String url = getOssFilePath(newFilePath,newFile);
System.out.println(url);
if(StringUtils.isNotEmpty(url)){
newFile.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 将oss上传文件地址 还原成 目标文件
* @param oss_url:Word文档的oos url全地址
*/
public String getResourceName(String oss_url,String basePath){
String resource="";
//域名
String oss_domain = OSSConstant.OSS_PIC_URL;
String file_name = oss_url.replace(oss_domain, "");
//获取oss文件byte[]
byte[] oss_byte = ossServiceImpl.getOssFileByteArray(file_name);
String targetPath=basePath+getNewFilePath1(oss_url);
//将字节数组还原为文件
ossServiceImpl.byteArrayToFile(oss_byte, targetPath);
resource=targetPath;
return resource;
}
/**
* 新的文件名
* @param fileName
* @return
*/
public String getNewFilePath1(String fileName){
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
//生成新的文件名
String newfilename = "";
Date now = new Date();
SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
newfilename += date.format(now) + "";
SimpleDateFormat time = new SimpleDateFormat("HHmmssSSS");
newfilename += time.format(now);
newfilename += "-" + new Random().nextInt(1000) + "." + fileExt;
return newfilename;
}
/**
* 生成的Word上传oos
* @param fileName
* @param newFile
* @return
*/
public String getOssFilePath(String fileName,File newFile){
String url = "";
try {
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
//生成新的文件名
String newfilename = "file/";
Date now = new Date();
SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
newfilename += date.format(now) + "/";
SimpleDateFormat time = new SimpleDateFormat("HHmmssSSS");
newfilename += time.format(now);
newfilename += "_" + new Random().nextInt(1000) + "." + fileExt;
FileInputStream fis = new FileInputStream(newFile);
//文件上传到oss
ossService.uploadFile(newfilename, fis);
url = OSSConstant.OSS_PIC_URL + newfilename;
}catch (Exception e) {
e.printStackTrace();
}
return url;
}
}
2.4 添加ExportWordController
package com.example.ossdemo.controller;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.example.ossdemo.service.ExportWordService;
/**
* 导出word
* @author Administrator
*
*/
@RequestMapping("/exportWord")
@RestController
public class ExportWordController {
@Autowired
private ExportWordService exportWordService;
/**
* 进入导出页面
* @return
*/
@RequestMapping("/index")
public ModelAndView toIndex(){
return new ModelAndView("export/index");
}
/**
* 导出销售订单信息(导出word)
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value="/exportOrderContractInfo",method = RequestMethod.POST)
public Map<String, Object> exportOrderContractInfo(HttpServletRequest request) throws Exception{
return exportWordService.exportOrderContractInfo(request);
}
}
2.5 创建jsp文件,调用导出方法
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<head>
<!-- easyUI -->
<link rel="stylesheet" href="<%=basePath %>/js/jquery-easyui-1.7.0/themes/default/easyui.css">
<link rel="stylesheet" href="<%=basePath %>/js/jquery-easyui-1.7.0/themes/icon.css">
<link rel="stylesheet" href="<%=basePath %>/css/common.css">
<script type="text/javascript" src="<%=basePath %>/js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="<%=basePath %>/js/jquery-easyui-1.7.0/jquery.easyui.min.js"></script>
<script type="text/javascript" src="<%=basePath %>/js/jquery-easyui-1.7.0/locale/easyui-lang-zh_CN.js"></script>
<!-- layer 弹出层 -->
<script type="text/javascript" src="<%=basePath %>/js/layer/layer.js"></script>
<link rel="stylesheet" href="<%=basePath %>/js/layui-v2.5.6/css/layui.css">
<style>
.m1{
margin-left: 10px;
}
.s1{
font-weight: bold;
color:#1e9fff;
}
.m2{
margin-bottom: 10px;
}
</style>
</head>
<body class="easyui-layout">
<h1 class="m1">SpringBoot+oss实现根据word模板生成Word,文件地址保存在oss中:</h1>
<div class="easyui-tabs" style="width:700px;height:350px;margin: 10px 0 0 10px;">
<div title="导出销售订单" style="padding:10px">
<div class="m2" style="margin-top: 30px;">
需求:将word模板上传到oss中,然后根据返回的模板地址进行生成word,最后把生成的Word再上传到oss并返回oss文件地址。
</div>
<div class="m2" style="margin-top: 30px;">
word模板地址(oss):<input type="text" id="url3" class="easyui-textbox" style="width:600px;" value="http://xiaofang-001.oss-cn-shanghai.aliyuncs.com/file/20201216/093915477_23.docx" readonly="readonly">
</div>
<a href="#" class="easyui-linkbutton" onclick="downloadTemplate();" >下载word模板地址</a>
<div class="m2" style="margin-top: 30px;">
使用<span class="s1">POI-tl</span>根据word模板动态生成word(包含动态表格)
</div>
<a href="#" class="easyui-linkbutton" onclick="doExportWord3();" data-options="iconCls:'icon-save'">导出销售订单</a>
</div>
</div>
<script type="text/javascript">
//下载word模板
function downloadTemplate(){
console.log($("#url3").val())
window.location.href=$("#url3").val();
}
//导出word(包含动态表格)
function doExportWord3(){
window.location.href="<%=basePath%>/exportWord/exportOrderContractInfo";
}
</script>
</body>
</html>
源码点击此处下载
参考资料:
地表最细阿里云OSS开通和文件上传demo,巨细 yeah
开通阿里云服务存储OSS
springboot整合阿里云OSS实现文件上传
相关文章
- Springboot读取application.properties/application.yml文件的shunx
- springboot开发中的领域模型pojo
- SpringBoot之:SpringBoot中使用HATEOAS
- SpringBoot word文件转pdf
- Springboot 获取 /resources 目录资源文件的 9 种方法
- SpringBoot修改默认端口号
- 指定springboot启动文件
- springboot(四)
- springboot文件下载功能开发!
- SpringBoot入门-批量操作优化
- SpringBoot 测试类 @RunWith & @SpringBootTest
- 一小时学会使用springboot操作阿里云OSS实现文件上传,下载,删除(附源码)
- 直接替换Springboot jar包中的文件
- springboot创建自定义starter
- 基于Hbase和SpringBoot的分布式HOS文件存储系统
- 如何基于SpringBoot+Docker构建公司级别的远程调试
- 基于SpringBoot框架实现的博客发布网站 附带运行指导文档
- SpringBoot+CAS整合服务端和客户端实现SSO单点登录与登出快速入门上手
- SpringBoot整合Servlet的两种方式
- SpringBoot项目使用hutool工具进行HttpClient接口调用的处理(文件上传)
- springboot读取jar中resource下的文件
- SpringBoot文件上传下载
- SpringBoot+Vue.js实现大文件分片上传、断点续传与极速秒传