阿里云OSS存储基于JAVA基本使用(一)

时间:2022-01-07 09:15:54

前段时间公司让研究阿里云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.uploadFile(File file, String fileType)  //单文件上传,type:文件后缀名
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和文件名都相同的

总结:
  1. 本例只是简单的运用,当然还有更高级的应用暂时还没有研究,希望以后有空再分享出来。
  2. 其中很多例子,在官方的SDK中都有,本文只是展示了对于我这里适用的方式,其他的多种配置方式请参考官方文档。
  3. 如有问题,可以提出,希望能够交流和共同学习。
  4. 本文示例皆为原创,转载请注明出处。