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"};/*** 上传文件处理逻辑*/@Overridepublic boolean uploadFile(String filepath, InputStream inputstream) {return upload(filepath, inputstream);}/*** oss文件下载处理逻辑*/@Overridepublic 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 {// 清空responseresponse.reset();// 设置response的Headerresponse.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 {// 关闭clientossClient.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) {// 关闭clientossClient.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);// 列举ObjectObjectListing 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 {// 关闭clientossClient.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 {// 关闭clientossClient.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 {// 关闭clientossClient.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 {// 关闭clientossClient.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 {// 关闭clientossClient.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 {// 关闭clientossClient.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 {// 关闭clientossClient.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 {// 关闭clientossClient.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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {// 4.释放资源try {if (is != null) {// 表示当文打开时,才需要通知操作系统关闭is.close();}} catch (IOException e) {// TODO Auto-generated catch blocke.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 blocke.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 {@Autowiredprivate 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");}//最大文件大小 100Mlong maxSize = 104857600;//最大文件大小 10Mlong 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{@Autowiredprivate OssService ossService;@Autowiredprivate OssServiceImpl ossServiceImpl;/*** 导出订单合同word*/@Overridepublic Map<String, Object> exportOrderContractInfo(HttpServletRequest request) throws Exception {Map<String, Object> result = new HashMap<String, Object>();//模拟数据请求,组装必要数据Map<String, Object> data = new HashMap<String, Object>();//导出wordexportWordOrderInfo(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);//文件上传到ossossService.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 {@Autowiredprivate 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实现oss文件的上传与下载相关推荐

  1. SpringBoot+Vue3实现文件的上传和下载

    目录 前言 上传前端页面 上传后端代码 下载后端代码 下载前端代码 总结 参考文献 前言 上传文件和下载文件是我们平时经常用到的功能,接下来就让我们用SpringBoot,Vue3和ElementPl ...

  2. SpringBoot 项目将文件图片资源上传到本地静态资源文件夹下(指定文件夹下)

    1.SpringBoot 项目将文件图片资源上传到本地静态资源文件夹下(指定文件夹下) 最终效果: 前端浏览本地文件,点击上传至本地resources/static/images/imgWall下 2 ...

  3. iOS阿里云对象存储 OSS文件的上传/下载的实现

    之前的项目中,图片语音等资源文件都是直接上传数据流给服务器,然后服务器进行处理和存储.最近的这个项目,服务器直接开的OSS,然后客户端直接使用阿里云提供的上传下载功能来上传和下载资源. 阿里云对图片的 ...

  4. 使用阿里云OSS实现文件的上传、下载、删除及修改功能

    一.配置OSS相关配置信息 1.要配置 OSS 相关配置信息,您可以按照以下步骤操作: 登录阿里云控制台,进入 OSS 控制台,创建一个新的 OSS Bucket,并记录下以下信息:Bucket 名称 ...

  5. (十六)admin-boot项目之文件存储上传与下载minio

    (十六)文件存储上传与下载 项目地址:https://gitee.com/springzb/admin-boot 如果觉得不错,给个 star 简介: 这是一个基础的企业级基础后端脚手架项目,主要由s ...

  6. SpringMVC实现文件的上传和下载

    SpringMVC实现文件的上传和下载http://www.bieryun.com/1120.html 前些天一位江苏经贸的学弟跟我留言问了我这样一个问题:"用什么技术来实现一般网页上文件的 ...

  7. Akka实战:HTTP大文件断点上传、下载,秒传

    2019独角兽企业重金招聘Python工程师标准>>> 访问:https://github.com/yangbajing/scala-applications/tree/master ...

  8. 初学Java Web(7)——文件的上传和下载

    文件上传 文件上传前的准备 在表单中必须有一个上传的控件 <input type="file" name="testImg"/> 因为 GET 方式 ...

  9. SpringMVC实现文件的上传与下载

    文件的上传与下载可以说是工作中经常使用的功能,现在整理一下,希望能够给大家一个参考.这里以 Maven 的形式来创建项目,相关的配置文件会把主要的内容列出来,其他头文件信息不再一一全部的列出.最后会把 ...

最新文章

  1. 再有人问你MySQL是如何查询数据的,请把这篇文章甩给他!
  2. Windows 技术篇-win7利用系统自带工具关闭开机启用程序,不使用杀毒软件设置开机启动项
  3. ios android 内存不足,怎样解决手机内存不足?iOS系统可以试试这些方法
  4. pythin怎么根据月份获取月初和月末_信息流是什么?到底应该怎么去做?
  5. Silverlight之Button控件简单自定义
  6. SQL Server数据库学习笔记-三大范式
  7. golang中如何使用http,socket5代理
  8. Lapack求解线性方程组
  9. P3819 松江1843路
  10. JNI引用溢出导致的重启问题分析
  11. Cadence Allegro PCB设计88问解析(十二) 之 Allegro中两种单位显示设置
  12. 计算机的性能及评估标准
  13. 下列属于mysql流程控制的是什么_下面选项中,不属于MySQL中流程控制语句的有...
  14. 算法导论 2-3 霍纳(Horner)规则的正确性
  15. 使用sql语句在命令行下载mysql表格数据
  16. 中国传统色的魅力|这8组中国风传统颜色你一定要收藏
  17. C#如何新建Excel
  18. 互联网、因特网及万维网之间的区别与联系
  19. python编程源码
  20. 【服务器raid数据恢复】RAID5两块盘离线的数据恢复案例

热门文章

  1. 计算机ps基础考试题,2017年计算机一级PS考试模拟题及答案
  2. 登录时动态验证码的使用
  3. 实操qq群排名技术半小时全国各地区排名第一
  4. 面试逻辑题和答案(二)
  5. INA219 电流计模块
  6. 办公文档被误删如何用EasyRecovery恢复
  7. NVIDIA Jetson TK1开发板
  8. CnOpenData中国外观设计专利基本信息数据
  9. Camstar 大数据之数据处理
  10. wx.getFuzzyLocation BUG 微信小程序官方BUG 临时处理办法