玩转OSS

对象存储OSS

  • 定义
  • 文档地址
  • 常用元素解释
    • service
    • bucket
    • object
    • endpoint
    • key
  • 好用API
    • 检查文件是否存在
    • 文件之间互相拷贝
    • 文件上传
  • 扩展
    • 文件下载到服务器
    • 文件夹下载到服务器,并根据条件分类下载到子文件夹
    • 文件夹下载到浏览器,并根据条件分类下载到子文件夹,打zip包
    • 网络图片直接下载到服务器本地
    • 服务器本地文件夹打成zip包
  • 暂时先到这里吧

定义

对象存储服务(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
public static void toZipExpand(List 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 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);
                }

            }
        }
    }
}

暂时先到这里吧

你可能感兴趣的:(后端,OSS)