前段时间公司让研究阿里云OSS,说计划会用起来。OSS就是一个阿里提供的在线存储服务,其实原先公司自己搭建的文件服务器也就能用,不过可能是为了以后的业务扩大着想,让提前研究使用了。OSS的基本概念他官网上有很多资料,我这里也就不再说了。研究了一整子,整理了一些方法,所以这里记录出来。本人是小白一枚,一下的知识竟可能的浅显,但也是我自己研究使用的思路,开始也没有找到一篇全面的使用手册,因为官方的SDK也是简洁的不能再简洁了。
本篇文章希望你先看完官方的API了解一下OSS基本语法和概念再来应该比较容易懂。
1.首先确保你已经注册并开通了OSS服务,并在控制台建立好了bucket,并获取到了accessKeyId和accessKeySecret
2.创建一个配置文件,里面存放OSS需要的endpoit和一些以后可能会改定的配置。
config.properties:
#阿里云OSS配置 endpoint = http://oss-cn-shenzhen.aliyuncs.com //可以选择其他的地址 bucketName = ft-pic //已经在控制台创建的bucket picLocation = CDoc/cms/ //你上传文件的保存路径,如果bucket中不存在则创建(其实原理并不是文件夹,只是文件名,详情请先阅读官方文档) accessKeyId = *********** //相应的id和key值,请填写你具体的值,这里不方便展示我自己的。 accessKeySecret = ************
3.创建一个读取配置文件的工具类,这并不是必须的,你可以按照自己的方式来实现配置的调取
SystemConfig.java:
import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 读取后缀名为“.properties”的文件 * @author * */ public class SystemConfig { private static final String CONFIG_PROPERTIES="config.properties"; public static String getConfigResource(String key) throws IOException{ ClassLoader loader = Thread.currentThread().getContextClassLoader(); Properties properties = new Properties(); InputStream in = loader.getResourceAsStream(CONFIG_PROPERTIES); properties.load(in); String value = properties.getProperty(key); // 编码转换,从ISO-8859-1转向指定编码 value = new String(value.getBytes("ISO-8859-1"), "UTF-8"); in.close(); return value; } }
4.创建一个OSS配置类,用来方便的获取基本信息。
OSSConfig.java:
/** * @ClassName: OSSConfig * @Description: OSS配置类 * @author AggerChen * @date 2016年11月4日 下午3:58:36 */ class OSSConfig{ private String endpoint; //连接区域地址 private String accessKeyId; //连接keyId private String accessKeySecret; //连接秘钥 private String bucketName; //需要存储的bucketName private String picLocation; //图片保存路径 public OSSConfig() { try { this.endpoint = SystemConfig.getConfigResource("endpoint"); this.bucketName = SystemConfig.getConfigResource("bucketName"); this.picLocation = SystemConfig.getConfigResource("picLocation"); this.accessKeyId = SystemConfig.getConfigResource("accessKeyId"); this.accessKeySecret = SystemConfig.getConfigResource("accessKeySecret"); } catch (IOException e) { e.printStackTrace(); } } public String getEndpoint() { return endpoint; } public void setEndpoint(String endpoint) { this.endpoint = endpoint; } public String getAccessKeyId() { return accessKeyId; } public void setAccessKeyId(String accessKeyId) { this.accessKeyId = accessKeyId; } public String getAccessKeySecret() { return accessKeySecret; } public void setAccessKeySecret(String accessKeySecret) { this.accessKeySecret = accessKeySecret; } public String getBucketName() { return bucketName; } public void setBucketName(String bucketName) { this.bucketName = bucketName; } public String getPicLocation() { return picLocation; } public void setPicLocation(String picLocation) { this.picLocation = picLocation; } }
5.编写OSS上传工具类
OSSUploadUtil.java:
package com.fortis.cms.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.UUID; import com.aliyun.oss.ClientException; import com.aliyun.oss.OSSClient; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.DeleteObjectsRequest; import com.aliyun.oss.model.DeleteObjectsResult; import com.aliyun.oss.model.GenericRequest; import com.aliyun.oss.model.ObjectMetadata; import com.aliyun.oss.model.PutObjectRequest; /** * * @ClassName: OSSUploadUtil * @Description: 阿里云OSS文件上传工具类 * @author AggerChen * @date 2016年11月3日 下午12:03:24 */ public class OSSUploadUtil { private static OSSConfig config = null; /** * * @MethodName: uploadFile * @Description: OSS单文件上传 * @param file * @param fileType 文件后缀 * @return String 文件地址 */ public static String uploadFile(File file,String fileType){ config = config==null?new OSSConfig():config; String fileName = config.getPicLocation()+UUID.randomUUID().toString().toUpperCase().replace("-", "")+"."+fileType; //文件名,根据UUID来 return putObject(file,fileType,fileName); } /** * * @MethodName: updateFile * @Description: 更新文件:只更新内容,不更新文件名和文件地址。 * (因为地址没变,可能存在浏览器原数据缓存,不能及时加载新数据,例如图片更新,请注意) * @param file * @param fileType * @param oldUrl * @return String */ public static String updateFile(File file,String fileType,String oldUrl){ String fileName = getFileName(oldUrl); if(fileName==null) return null; return putObject(file,fileType,fileName); } /** * * @MethodName: replaceFile * @Description: 替换文件:删除原文件并上传新文件,文件名和地址同时替换 * 解决原数据缓存问题,只要更新了地址,就能重新加载数据) * @param file * @param fileType 文件后缀 * @param oldUrl 需要删除的文件地址 * @return String 文件地址 */ public static String replaceFile(File file,String fileType,String oldUrl){ boolean flag = deleteFile(oldUrl); //先删除原文件 if(!flag){ //更改文件的过期时间,让他到期自动删除。 } return uploadFile(file, fileType); } /** * * @MethodName: deleteFile * @Description: 单文件删除 * @param fileUrl 需要删除的文件url * @return boolean 是否删除成功 */ public static boolean deleteFile(String fileUrl){ config = config==null?new OSSConfig():config; String bucketName = OSSUploadUtil.getBucketName(fileUrl); //根据url获取bucketName String fileName = OSSUploadUtil.getFileName(fileUrl); //根据url获取fileName if(bucketName==null||fileName==null) return false; OSSClient ossClient = null; try { ossClient = new OSSClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret()); GenericRequest request = new DeleteObjectsRequest(bucketName).withKey(fileName); ossClient.deleteObject(request); } catch (Exception oe) { oe.printStackTrace(); return false; } finally { ossClient.shutdown(); } return true; } /** * * @MethodName: batchDeleteFiles * @Description: 批量文件删除(较快):适用于相同endPoint和BucketName * @param fileUrls 需要删除的文件url集合 * @return int 成功删除的个数 */ public static int deleteFile(List<String> fileUrls){ int deleteCount = 0; //成功删除的个数 String bucketName = OSSUploadUtil.getBucketName(fileUrls.get(0)); //根据url获取bucketName List<String> fileNames = OSSUploadUtil.getFileName(fileUrls); //根据url获取fileName if(bucketName==null||fileNames.size()<=0) return 0; OSSClient ossClient = null; try { ossClient = new OSSClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret()); DeleteObjectsRequest request = new DeleteObjectsRequest(bucketName).withKeys(fileNames); DeleteObjectsResult result = ossClient.deleteObjects(request); deleteCount = result.getDeletedObjects().size(); } catch (OSSException oe) { oe.printStackTrace(); throw new RuntimeException("OSS服务异常:", oe); } catch (ClientException ce) { ce.printStackTrace(); throw new RuntimeException("OSS客户端异常:", ce); } finally { ossClient.shutdown(); } return deleteCount; } /** * * @MethodName: batchDeleteFiles * @Description: 批量文件删除(较慢):适用于不同endPoint和BucketName * @param fileUrls 需要删除的文件url集合 * @return int 成功删除的个数 */ public static int deleteFiles(List<String> fileUrls){ int count = 0; for (String url : fileUrls) { if(deleteFile(url)){ count++; } } return count; } /** * * @MethodName: putObject * @Description: 上传文件 * @param file * @param fileType * @param fileName * @return String */ private static String putObject(File file,String fileType,String fileName){ config = config==null?new OSSConfig():config; String url = null; //默认null OSSClient ossClient = null; try { ossClient = new OSSClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret()); InputStream input = new FileInputStream(file); ObjectMetadata meta = new ObjectMetadata(); // 创建上传Object的Metadata meta.setContentType(OSSUploadUtil.contentType(fileType)); // 设置上传内容类型 meta.setCacheControl("no-cache"); // 被下载时网页的缓存行为 PutObjectRequest request = new PutObjectRequest(config.getBucketName(), fileName,input,meta); //创建上传请求 ossClient.putObject(request); url = config.getEndpoint().replaceFirst("http://","http://"+config.getBucketName()+".")+"/"+fileName; //上传成功再返回的文件路径 } catch (OSSException oe) { oe.printStackTrace(); return null; } catch (ClientException ce) { ce.printStackTrace(); return null; } catch (FileNotFoundException e) { e.printStackTrace(); return null; } finally { ossClient.shutdown(); } return url; } /** * * @MethodName: contentType * @Description: 获取文件类型 * @param FileType * @return String */ private static String contentType(String fileType){ fileType = fileType.toLowerCase(); String contentType = ""; switch (fileType) { case "bmp": contentType = "image/bmp"; break; case "gif": contentType = "image/gif"; break; case "png": case "jpeg": case "jpg": contentType = "image/jpeg"; break; case "html":contentType = "text/html"; break; case "txt": contentType = "text/plain"; break; case "vsd": contentType = "application/vnd.visio"; break; case "ppt": case "pptx":contentType = "application/vnd.ms-powerpoint"; break; case "doc": case "docx":contentType = "application/msword"; break; case "xml":contentType = "text/xml"; break; case "mp4":contentType = "video/mp4"; break; default: contentType = "application/octet-stream"; break; } return contentType; } /** * * @MethodName: getBucketName * @Description: 根据url获取bucketName * @param fileUrl 文件url * @return String bucketName */ private static String getBucketName(String fileUrl){ String http = "http://"; String https = "https://"; int httpIndex = fileUrl.indexOf(http); int httpsIndex = fileUrl.indexOf(https); int startIndex = 0; if(httpIndex==-1){ if(httpsIndex==-1){ return null; }else{ startIndex = httpsIndex+https.length(); } }else{ startIndex = httpIndex+http.length(); } int endIndex = fileUrl.indexOf(".oss-"); return fileUrl.substring(startIndex, endIndex); } /** * * @MethodName: getFileName * @Description: 根据url获取fileName * @param fileUrl 文件url * @return String fileName */ private static String getFileName(String fileUrl){ String str = "aliyuncs.com/"; int beginIndex = fileUrl.indexOf(str); if(beginIndex==-1) return null; return fileUrl.substring(beginIndex+str.length()); } /** * * @MethodName: getFileName * @Description: 根据url获取fileNames集合 * @param fileUrl 文件url * @return List<String> fileName集合 */ private static List<String> getFileName(List<String> fileUrls){ List<String> names = new ArrayList<>(); for (String url : fileUrls) { names.add(getFileName(url)); } return names; } }
6.调用测试,OSSUploadUtil工具类对外只提供了几个方法:
OSSUploadUtil.updateFile(File file, String fileType, String oldUrl)
//更新文件:只更新内容,不更新文件名和文件地址。
OSSUploadUtil.replaceFile(File file, String fileType, String oldUrl)
//替换文件,删除源文件并上传新文件,文件名和地址也改变
OSSUploadUtil.deleteFile(List<String> fileUrls)
//删除多文件,根据问价url来自定获取其中的bucket和文件名,用于bucket和文件名可能存在不同的,循环调用
deleteFile方法
OSSUploadUtil.deleteFile(String fileUrl)
//删除单文件
OSSUploadUtil.deleteFiles(List<String> fileUrls)
//删除多文件,根据配置直接取删除多个文件,bucket和文件地址从配置中获取,用于多文件bucket和文件名都相同的
总结:
- 本例只是简单的运用,当然还有更高级的应用暂时还没有研究,希望以后有空再分享出来。
- 其中很多例子,在官方的SDK中都有,本文只是展示了对于我这里适用的方式,其他的多种配置方式请参考官方文档。
- 如有问题,可以提出,希望能够交流和共同学习。
- 本文示例皆为原创,转载请注明出处。