OSS阿里云存储——整合Spring文件上传,实现动静网站资源分离
来源:互联网 发布:ceph源码分析 常涛 编辑:程序博客网 时间:2024/05/17 20:32
写在前面
在日常学习或开发java web项目的过程中,难免会遇到各种各样的文件上传问题。传统做法或固有思路,一向是把这些用户上传的静态资源保存在自己的服务器中。这也是初学者普遍的做法。但是,长此以往,大量用户累积的用户静态资源文件,势必会大量占用服务器的存储空间,降低服务器的性能,同时也增加了网站维护的成本。
于是,另一种做法营运而生,就是把网站的静态资源和动态资源实现分离。增加一台服务器专门用来保存静态文件,这不失为一种好办法。但小编今天分享的另一种方法是在第三方云存储服务器的基础上,实现自己的文件上传以及文件云存储,达到网站资源动静分离的目的。
关于阿里云OSS云存储服务器的具体资料和相关文档以及各个语言的API请读者自行百度或浏览官网学习,这里就不做过多的赘述。传送门:阿里云官网OOS对象服务器
以下小编主要分享Spring+OSS云存储服务上传文件的具体操作。
准备工作
1.阿里云账号
2.一台阿里云存储服务器(包半年6.00元左右,购买以及基本配置请参考官网)
开发环境以及工具
1.java 1.8
2.idea
3.Tomcat9 主要用来测试
4.maven3.5
你必须知道的OSS对象服务器的基本概念
1.存储空间(Bucket)
存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。
2.对象/文件(Object)
对象是 OSS 存储数据的基本单元,也被称为 OSS 的文件
3.Region(地域)
Region 表示 OSS 的数据中心所在的地域,物理位置。
4.Endpoint(访问域名)
Endpoint 表示 OSS 对外服务的访问域名。
5.AccessKey(访问密钥)
AccessKey,简称 AK,指的是访问身份验证中用到的 AccessKeyId 和AccessKeySecret。OSS 通过使用 AccessKeyId 和 AccessKeySecret 对称加密的方法来验证某个请求的发送者身份。AccessKeyId 用于标识用户,AccessKeySecret 是用户用于加密签名字符串和 OSS 用来验证签名字符串的密钥,其中 AccessKeySecret 必须保密。对于 OSS 来说,AccessKey 的来源有:
Bucket 的拥有者申请的 AccessKey。
被 Bucket 的拥有者通过 RAM 授权给第三方请求者的 AccessKey。
被 Bucket 的拥有者通过 STS 授权给第三方请求者的 AccessKey。
以上列出的只是部分基础的概念,详情请参考官方文档。
项目组织结构
此项目本来是一个web项目,用到的数据库是mongodb,主要用来记录接口访问日志。化红线的是上传文件的主要功能类。因此,其他配置文件中的具体配置在此不详加赘述,这里只提供基本的思路。更加完美的功能请自行完善。
OSS 接口的配置使用和基本操作封装
使用前导入maven依赖
<dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>2.7.0</version> </dependency>
AliOSSConfig.java
/** * @author longping jie * @name AliOSSConfig * @description the class is 阿里云oos上传客户端对象的配置类 * @date 2017/9/20 */public class AliOSSConfig { public static String END_POINT; public static String ACCESS_KEY_ID; public static String ACCESS_KEY_SECRET; public static int VISIT_GRADE = 3; static { //外部接入入口 END_POINT = PropertiesHelper.getValueByKey("END_POINT"); //秘钥id ACCESS_KEY_ID = PropertiesHelper.getValueByKey("ACCESS_KEY_ID"); //秘钥对应该是 ACCESS_KEY_SECRET = PropertiesHelper.getValueByKey("ACCESS_KEY_SECRET"); }}
这些常量配置从properties配置文件中读取,properties文件和其操作的封装自行处理。
AliOSSBaseTool.java 封装一些OSS的基本操作
package com.longge.upload.util;import com.aliyun.oss.OSSClient;import com.aliyun.oss.model.CannedAccessControlList;import com.aliyun.oss.model.CreateBucketRequest;import com.aliyun.oss.model.OSSObject;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import java.io.ByteArrayInputStream;/** * @author longping jie * @name AliOSSTool * @description the class is 阿里云OSS客户端工具类 * @date 2017/9/20 */public class AliOSSBaseTool { static Logger logger = LogManager.getLogger(AliOSSBaseTool.class); /** * 判断一个存储空间是否存在 * * @param ossClient * @param bucketName * @return */ public static boolean doesBucketExits(OSSClient ossClient, String bucketName) { return ossClient.doesBucketExist(bucketName); } /** * 创建一个存储空间 * 并给存储空间对外赋读写权限 * @param ossClient oss连接 * @param bucketName 存储空间名字 * @param grade 访问等级(1,2,3)(私有,公共读,公共读写) * @return 是否创建成功 */ public static boolean createBuckName(OSSClient ossClient, String bucketName, int grade) { boolean res; if (doesBucketExits(ossClient, bucketName)) return true; CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); switch (grade) { case 1: createBucketRequest.setCannedACL(CannedAccessControlList.Private); break; case 2: createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); break; case 3: createBucketRequest.setCannedACL(CannedAccessControlList.PublicReadWrite); break; default: createBucketRequest.setCannedACL(CannedAccessControlList.Private); break; } ossClient.createBucket(createBucketRequest); res = true; return res; } /** * 删除一个存储空间 * * @param ossClient oss连接 * @param bucketName 存储空间名字 */ public void deleteBucketName(OSSClient ossClient, String bucketName) { if (doesBucketExits(ossClient, bucketName)) { ossClient.deleteBucket(bucketName); } } /** * 创建一个文件夹 * * @param ossClient oss连接 * @param bucketName 存储空间名字 * @param folder 文件夹名 * @return true 创建成功 false文件夹已经存在 */ public static boolean createFolder(OSSClient ossClient, String bucketName, String folder) { if (!ossClient.doesObjectExist(bucketName, folder)) { ossClient.putObject(bucketName, folder, new ByteArrayInputStream(new byte[0])); OSSObject object = ossClient.getObject(bucketName, folder); String fileDir = object.getKey(); logger.debug("文件夹创建成功:{}", fileDir); return true; } return false; } /** * 删除一个文件夹 * * @param ossClient oss连接 * @param bucketName 存储空间名字 * @param folder 文件夹名 * @return true 删除成功 false文件夹已经存在 */ public static boolean deleteFolder(OSSClient ossClient, String bucketName, String folder) { if (ossClient.doesObjectExist(bucketName, folder)) { ossClient.deleteObject(bucketName, folder); logger.debug("删除文件夹成功:{}", folder); return true; } return false; } /** * 根据key删除OSS服务器上的文件 * @param ossClient oss连接 * @param bucketName 存储空间 * @param folder 模拟文件夹名 * @param key Bucket下的文件路径名+文件名 如:"upload/cake.jpg" */ public static void deleteFile(OSSClient ossClient,String bucketName,String folder,String key){ ossClient.deleteObject(bucketName,folder+key); logger.debug("删除:{}",bucketName+"下的文件:{}",folder+key+"成功!"); }}
AliOSSApplayUtil.java OOS应用工具类,封装图片上传
package com.longge.upload.util;import com.aliyun.oss.ClientException;import com.aliyun.oss.OSSClient;import com.aliyun.oss.OSSException;import com.aliyun.oss.model.*;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import java.io.*;import java.util.Date;import java.util.UUID;/** * @author longping jie * @name AliOSSUtil * @description the class is 阿里云应用工具类 * @date 2017/9/18 */public class AliOSSApplayUtil { private final static Logger log = LogManager.getLogger(AliOSSApplayUtil.class); private static String END_POINT=AliOSSConfig.END_POINT; private static String ACCESS_KEY_ID=AliOSSConfig.ACCESS_KEY_ID; private static String ACCESS_KEY_SECRET=AliOSSConfig.ACCESS_KEY_SECRET; /** * 获得oss连接对象 * @return oss连接对象 */ private static OSSClient ossClient(){ return new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); } /** * 上传文件 * * @param file 文件对象 * @return 保存文件在oos服务器上的路径,上传成功后返回文件的保存路径是一个url连接 * 直接指向云上的资源位置 */ public static String upload(File file,String bucketName,String folder) { if (file == null) { return null; } //创建OSS客户端 OSSClient ossClient = ossClient(); try (InputStream is = new FileInputStream(file)) { //判断文件容器是否存在,不存在则创建 AliOSSBaseTool.createBuckName(ossClient,bucketName,AliOSSConfig.VISIT_GRADE); AliOSSBaseTool.createFolder(ossClient,bucketName,folder); //文件名 String fileName = file.getName(); //文件大小 Long fileSize = file.length(); //创建上传文件的Metadata ObjectMetadata metadata = new ObjectMetadata(); //上传文件的长度 metadata.setContentLength(is.available()); //指定该object被下载时的网页的缓存行为 metadata.setCacheControl("no-cache"); //指定该object下设置Header metadata.setHeader("Pragma","no-cache"); //指定该object被下载时的内容编码方式 metadata.setContentEncoding("utf-8"); //文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成, //如果没有扩展名则填默认值application/octet-stream metadata.setContentType(getContentType(fileName)); //指定该Object被下载时的名称(指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称) metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte."); //上传文件 (上传文件流的形式) //此处上传文件 PutObjectResult putResult = ossClient.putObject(bucketName, folder+fileName, is, metadata); String fileHost = "http://"+bucketName+"."+END_POINT; if (null != putResult) { return fileHost+"/"+folder+fileName; } } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); }finally { // 关闭OSS服务,一定要关闭 ossClient.shutdown(); } return null; } /** * 通过文件名判断并获取OSS服务文件上传时文件的contentType * @param fileName 文件名 * @return 文件的contentType */ public static String getContentType(String fileName){ //文件的后缀名 String fileExtension = fileName.substring(fileName.lastIndexOf(".")); if(".bmp".equalsIgnoreCase(fileExtension)) { return "image/bmp"; } if(".gif".equalsIgnoreCase(fileExtension)) { return "image/gif"; } if(".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension) || ".png".equalsIgnoreCase(fileExtension) ) { return "image/jpeg"; } if(".html".equalsIgnoreCase(fileExtension)) { return "text/html"; } if(".txt".equalsIgnoreCase(fileExtension)) { return "text/plain"; } if(".vsd".equalsIgnoreCase(fileExtension)) { return "application/vnd.visio"; } if(".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) { return "application/vnd.ms-powerpoint"; } if(".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) { return "application/msword"; } if(".xml".equalsIgnoreCase(fileExtension)) { return "text/xml"; } //默认返回类型 return "image/jpeg"; }}upload方法是文件上传的具体方法,接收File file 参数,在此基础上可以对file进行缩放、裁剪等基础操作后,再传入,然后写入云服务器。上传文件成功后,会根据Controller中自定义的成功信息,返回成功状态,和文件保存的路径,可以把url返回前端界面展示。
Springmvc的multipart配置这个在配置文件中定义。
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8" /> <property name="maxUploadSize" value="104857600" /> <property name="maxInMemorySize" value="4096" /> </bean>
另一种使文件上传,性能更高的做法是,把自己的密钥(或者识别身份的东西)暂时授权给第三方用户(你的网站用户)用户可以直接POST调用阿里云的接口,即省去你自己的服务器中转。这样就更加快速而且高效地实现文件上传的目的。
OSS对象服务器大致的基本功能,小编就暂时分享到这里。有关OOS的细节,还请读者参考官方文档。文章中的不足之处,希望读者在评论区不吝赐教。代码经测试有效,在整合自己项目的过程中,遇到问题,欢迎在此讨论。整个项目的源码,小编完善后,会托管到GitHub或码云上,随后共享。欢迎大家关注…
- OSS阿里云存储——整合Spring文件上传,实现动静网站资源分离
- 整合阿里云OSS文件上传1
- 整合阿里云OSS文件上传2
- 文件上传-阿里云OSS-存储文件
- 阿里云对象存储OSS--实现随时随地上传文件到阿里云
- Laravel整合UEditor编辑器使用阿里云OSS存储(二)改造UEditor上传OSS
- Laravel整合UEditor编辑器使用阿里云OSS存储(二)改造UEditor上传OSS
- 阿里云OSS 上传文件
- 阿里云OSS 文件上传
- 阿里云存储OSS中设置上传文件content type
- 阿里云存储OSS golang语言上传文件示例。
- thinkPHP实现对象存储oss,将图片上传到阿里云oss
- 阿里云oss对象存储图片上传
- 阿里oss文件上传
- 阿里云上传文件,下载文件 oss
- OSS阿里云文件上传 demo
- Jfinal版阿里云OSS文件上传
- 阿里云OSS上传文件工具类
- 顺序表应用7:最大子段和之分治递归法
- Windows平台异常处理 开发中何时利用异常处理模块
- maven项目环境搭建
- centos7安装jdk环境
- c++(1) 类模板/构造函数/捕获异常 实例
- OSS阿里云存储——整合Spring文件上传,实现动静网站资源分离
- 浅谈单链表和顺序表
- eclipse中利用Maven逆向工程生成PO类以及mapper(mybatis)
- mysq数据库管理工具navicat基本使用方法
- Tomcat配置详解
- 分析插入与归并排序
- 贝叶斯推断简介
- 数组中只出现过一次的数字
- HTTPS证书配置(单向认证)