对象存储OSS
定义
对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
文档地址
包括入门、sdk、api、错误码等等等等。地址:https://help.aliyun.com/product/31815.html
常用元素解释
service、bucket、object、endpoint、key
service
service:bucket容器,里面放着自己拥有的所有bucket。
bucket
bucket:object容器,里面放着自己上传的所有object。
object
object:就是自己上传的文件。
endpoint
endpoint:自己创建bucket的时候选择的地域(北京、天津、杭州等等)。
示例:oss-cn-beijing.aliyuncs.com
key
key:目录+文件名(除了***.oss-cn-beijing.aliyuncs.com
之外的东西)。
示例:qinzy/aaa.png
好用API
常用的上传下载文档上面都很清晰了,看自己的上传需求用对应的方式就可以了。
下面说两个项目中用到的比较好用的api
检查文件是否存在
下载或者copy的时候先检查下数据源是否存在:ossClient.doesObjectExist(bucket, url)
文件之间互相拷贝
bucket1:源bucket,url1:源路径,bucket2:目标bucket,url2:目标路径
从一个bucket中copy一个文件到另一个bucket:ossClient.copyObject(bucket1,url1,bucket2,url2)
文件上传
//拿到aaa.png的读入流
InputStream inputStream = new FileInputStream("/etc/qinzy/aaa.png");
//上传到OSS,并重命名为bbb.png
ossClient.putObject(bucket, "ai/qinzy/bbb.png", inputStream);
扩展
文件下载到服务器
直接从oss下载文件到服务器:ossClient.getObject(new GetObjectRequest(bucket, url), new File(newUrl))
文件夹下载到服务器,并根据条件分类下载到子文件夹
思路:直接在服务器上根据条件创建对应的文件夹,再根据条件把不同的文件拷贝到不同的文件夹即可。
//创建文件夹
File file = new File(path);
if(!file.exists()){
file.mkdir();
}
文件夹下载到浏览器,并根据条件分类下载到子文件夹,打zip包
备注:实际上zip包是先生成,再往里面填充数据
思路1:先下载到服务器,再从服务器下载到浏览器,再删除服务器上面对应的文件夹
1、直接从oss下载文件到服务器:ossClient.getObject(new GetObjectRequest(bucket, url), new File(newUrl))
2、循环文件夹下面的所有文件,用response的输出流打包输出到浏览器,核心代码如下:
//注意,接口响应要设置为void,否则会报**多次响应异常**。
public void download(HttpServletResponse response){
//设置响应头格式
response.setContentType("application/octet-stream");
//处理文件名为中文的情况,和打包后的zip名
response.setHeader("Content-Disposition","attach;filename=" + new String("qinzy.zip".getBytes("UTF-8"), "ISO-8859-1"));
if(files.size()>0){
/** 压缩 */
ZipUtils.toZipExpand(files, response.getOutputStream());
//执行完后选择删除文件
for(int i=0;i<files.size();i++){
files.get(i).delete();
}
}
}
public static void toZipExpand(List<File> srcFiles , OutputStream out)throws RuntimeException {
private static final int BUFFER_SIZE = 2 * 1024;
long start = System.currentTimeMillis();
ZipOutputStream zos = null ;
try {
zos = new ZipOutputStream(out);//组装压缩包写出流out=response.getOutputStream()
for (File srcFile : srcFiles) {
byte[] buf = new byte[BUFFER_SIZE];//缓冲区大小
String name = srcFile.getName();//文件名
//按下面的组装好目录后,打成zip包后不同的文件会在不同的目录下,否则会都在根目录下!
zos.putNextEntry(new ZipEntry("qinzy" + File.separator+name));//组装文件夹目录
int len;
FileInputStream in = new FileInputStream(srcFile);//文件读入流读取文件
while ((len = in.read(buf)) != -1){//缓冲区循环读
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
}
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) +" ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils",e);
}finally{
if(zos != null){
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
思路2:直接从oss下载到浏览器,伪代码如下
//PS:这里的filePath在OSS文档上实际是key
String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
//文件名如果包含中文需要指定编码
response.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
OutputStream out = response.getOutputStream();//获取写出流
OSSObject ossObject = ossClient.getObject(bucketName, filePath);//拿到OSSObject
InputStream in = ossObject.getObjectContent();//获取读入流
//循环写出到浏览器
byte[] data = new byte[1024];
int len = 0;
while ((len = in.read(data)) != -1) {
out.write(data, 0, len);
}
out.flush();
out.close();
in.close();
//PS:如果需要zip包格式,可以像上面**思路1**一样,循环一下,组装成文件夹,打成zip包输出到浏览器
网络图片直接下载到服务器本地
//PS:以下为下载到服务器本地demo,如需直接下载到浏览器,参考上面的文件夹下载到浏览器,用response写出流输出到浏览器即可!
//urlList:图片路径集合
//path:服务器存放图片的目录(文件夹位置)
//imgName:下载下来的图片路径
public static void downloadPicture(List<String> urlList, String path, String imgName) throws Exception {
if(urlList==null||urlList.size()==0){
return;
}
File file = new File(path);
if(!file.exists()){
file.mkdir();
}
URL url = null;
FileOutputStream fileOutputStream =null;
InputStream inputStream =null;
for (String urlString : urlList) {
try {
url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0");
connection.setConnectTimeout(10 * 1000);
connection.setReadTimeout(15 * 1000);
inputStream = connection.getInputStream();
byte[] buffer = new byte[1024];
int length;
fileOutputStream= new FileOutputStream(path+ File.separator+ imgName);
while ((length = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, length);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
inputStream.close();
fileOutputStream.flush();
fileOutputStream.close();
}
}
}
服务器本地文件夹打成zip包
public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
throws RuntimeException{
long start = System.currentTimeMillis();
ZipOutputStream zos = null ;
try {
zos = new ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(sourceFile,zos,sourceFile.getName(),KeepDirStructure);
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) +" ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils",e);
}finally{
if(zos != null){
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void compress(File sourceFile, ZipOutputStream zos, String name,
boolean KeepDirStructure) throws Exception{
byte[] buf = new byte[BUFFER_SIZE];
if(sourceFile.isFile()){
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1){
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
//是文件夹
File[] listFiles = sourceFile.listFiles();
if(listFiles == null || listFiles.length == 0){
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if(KeepDirStructure){
// 空文件夹的处理
zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
zos.closeEntry();
}
}else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (KeepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
} else {
compress(file, zos, file.getName(),KeepDirStructure);
}
}
}
}
}