首页 > 技术文章 > 八、java操作swift对象存储(静态大对象)

yclh 2021-08-03 19:35 原文

系列导航

一、swift对象存储环境搭建

二、swift添加存储策略

三、swift大对象--动态大对象

四、swift大对象--静态态大对象

五、java操作swift对象存储(官网样例)

六、java操作swift对象存储(resultful方式实现)

七、java操作swift对象存储(动态大对象)

八、java操作swift对象存储(静态大对象)

    前面讲了如何使用swift的静态大对象那么java如何操作呢?如下的例子是我自己写的不是官网的(官网的没找到),swift系列到这就结束了,从安装到java使用都展现给大家了希望能对需要学习swift对象存储的朋友有所帮助。

一、依赖

   与  六、java操作swift对象存储(resultful方式实现)  一样这里就不重复了。

 

二、重要方法类StaticLargeObject.java

package largeobject;

import java.io.File;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import org.apache.http.Header;
import base.ResultFulBase;
import largeobject.tool.CutFileUtil;

//静态大对象操作
public class StaticLargeObject {

     //访问swift的url地址
     public static String X_Storage_Url = "";
     
     //访问swift的令牌
     public static String X_Auth_Token = "";
    
     public static ResultFulBase resultFulBase = null;
     
     public StaticLargeObject(ResultFulBase resultFulBase){
         X_Storage_Url = resultFulBase.X_Storage_Url;
         X_Auth_Token = resultFulBase.X_Auth_Token;
         this.resultFulBase = resultFulBase;
     }
     
     //上传静态大对象
        /* 参数说明
         * objectContainerName:存储对象分块的容器名称(实际上所有的段都可以在不同的容器里)
         * maniFestContainerName:存储manifest对象的容器
         * FilePath:上传的文件路径
         * objectName:上传后的对象名称
         * MBSize:切割文件的大小(单位MB)
         * 注:使用时如果每段数据的前缀重名会破坏文件的完整性,普通文件建议使用静态大对象
         */
        
        public static  void upload_Static_large_object(String objectContainerName,String maniFestContainerName,String FilePath,String objectName,long MBSize){
            CutFileUtil cutFileUtil = new CutFileUtil();
            Long  mbSzie = MBSize*1024*1024;
            File file = new File(FilePath);
            String fileName = file.getName();
            String path  = file.getParent()+"//";
            
            int count =0 ;
            count = cutFileUtil.cutFileBySize(FilePath, mbSzie, path );
            
            
            JSONArray jsonArray = new JSONArray();
            //上传可以改为多线程 获取信息单独出来
            for(int i =0;i<count;i++ ){
                resultFulBase.create_object(objectContainerName,i+"-"+fileName,path +i+"-"+fileName  );
                 get_container_object_attribute( objectContainerName,i+"-"+fileName ,jsonArray );
                 
                String partFilePath = path+i+"-"+fileName;
                //删除上传过的 切割文件
                File partFile = new File(partFilePath);
                partFile.delete();
            }
         
            System.out.println("************" +jsonArray.toString() );
           
            String manifest= jsonArray.toString();
                
            create_Static_manifest_object(maniFestContainerName,objectName,manifest);
     
            
        }
        
        
        //静态大对象获取对象的length和etag
        //curl http://127.0.0.1:8080/v1/AUTH_admin/container1/2.txt  -X GET  -H "X-Auth_Token: AUTH_tkf44c48c200e34f14850f6a8e3bc63f36"
        public static  void get_container_object_attribute(String containerName,String objectName,JSONArray jsonArray ){
            try {
                
                
                HttpHead  req = new HttpHead(X_Storage_Url+ "/"+containerName+ "/"+objectName);
           //     HttpGet req = new HttpGet(X_Storage_Url+ "/"+containerName+ "/"+objectName);
                req.addHeader("X-Auth-Token", X_Auth_Token);
                DefaultHttpClient httpclient = new DefaultHttpClient();
                HttpResponse rsp = httpclient.execute(req);
                System.out.println("----------------------------------------");
                System.out.println(rsp.getStatusLine());
                JSONObject object = new JSONObject();
                object.put("path", containerName+"/"+objectName);
                Header[] headers = rsp.getAllHeaders();
                for (int i = 0; i < headers.length; i++) {
                    System.out.println(headers[i]);
                    if(headers[i].toString().contains("Etag:")){
                        object.put("etag", headers[i].toString().replace("Etag: ",""));
                    }
                    if(headers[i].toString().contains("Content-Length:")){
                        object.put("size_bytes", headers[i].toString().replace("Content-Length: ",""));
                    }
                }
                System.out.println("----------------------------------------");
                jsonArray.put(object);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        
        
        //静态大对象上传manifest对象   切割后的段文件 大小要超过1M
        //curl -v -X PUT  -H  "X-Static-Large-Object: true" -H "X-Auth-Token: AUTH_tkb78213f9392f43cdbb6e9bee8d0cd31a"  "http://127.0.0.1:8080/v1/AUTH_admin/StaticContainer/myLargeFile?multipart-manifest=put&heartbeat=on"    -T  /opt/manifest.json
        public static  void create_Static_manifest_object(String containerName,String objectName,String manifest){
            try {
                HttpPut req = new HttpPut(X_Storage_Url+ "/"+containerName +"/"+objectName+"?multipart-manifest=put&heartbeat=on");
                req.addHeader("X-Auth-Token", X_Auth_Token);
                req.addHeader("X-Static-Large-Object", "true");
     
                StringEntity  entity1=new StringEntity(manifest);
                
              //  FileEntity entity1 = new FileEntity(file, "text/plain; charset=\"UTF-8\"");
                req.addHeader("Content-Type", "text/plain; charset=\"UTF-8\"");
                req.setEntity(entity1);

                DefaultHttpClient httpclient = new DefaultHttpClient();
                HttpResponse rsp = httpclient.execute(req);

                System.out.println("----------------------------------------");
                System.out.println(rsp.getStatusLine());
                Header[] headers = rsp.getAllHeaders();
                for (int i = 0; i < headers.length; i++) {
                    System.out.println(headers[i]);
                }
                System.out.println("----------------------------------------");

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
}

三、数据切割的类CutFileUtil.java

package largeobject.tool;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * <功能简要> <br>
 * <切割文件工具>
 *
 * @Author yc
 * @since
 */
public class CutFileUtil {

    
    
    public static void main(String[] args) throws Exception {
        CutFileUtil cutFileUtil = new CutFileUtil();
        int count =0 ;
        cutFileUtil.cutFileBySize("E://1.jpg", new Long(30000), "E://1/" );
    }
    
    /**
     * @param filePath 文件所在主机的路径 例:/home/gyt/nginx.tar
     * @param byteSize 拆分文件字节大小
     * @param saveAddr 拆分后的文件保存目录  /homt/gyt/
     * @return
     */
    public int  cutFileBySize(String filePath, Long byteSize, String saveAddr  ){
        List<String> fileNames = new ArrayList<String>();
        File file = new File(filePath);
        //计算总共段数
        int count = (int) Math.ceil(file.length()/(double)byteSize);
        int countLen = (count +"").length();
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(count * 2);
        
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,4,1,TimeUnit.SECONDS, workQueue );
        
        //ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,4,1,TimeUnit.SECONDS,new ArrayBlockingQueue<>(count * 2));
        
        
        //时间戳
        String timeStamp = String.valueOf(System.currentTimeMillis());

        for (int i = 0; i < count; i++) {
            //分段文件名
           // String fileName = timeStamp + "-" + leftPad((i+1) +"", countLen, '0') + "-" +file.getName();
            String fileName =    i+ "-" +file.getName();
            threadPoolExecutor.execute(new SplitRunnable(byteSize.intValue(), fileName, file, i*byteSize, saveAddr));
            fileNames.add(fileName);
        }
        threadPoolExecutor.shutdown();
        while (true){
            if (threadPoolExecutor.isTerminated()){
                return count;
            }
            try {
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        
    }

    public static String leftPad(String str, int length, char ch){
        if (str.length() >= length){
            return str;
        }
        char[] chs = new char[length];
        Arrays.fill(chs, ch);
        char[] src = str.toCharArray();
        System.arraycopy(src, 0, chs, length - src.length, src.length);
        return new String(chs);
    }

    private class SplitRunnable implements Runnable{
        int byteSize;
        String fileName;
        File originFile;
        Long startPos;
        String currentWorkDir;

        public SplitRunnable(int byteSize, String fileName, File originFile, Long startPos, String currentWorkDir) {
            this.byteSize = byteSize;
            this.fileName = fileName;
            this.originFile = originFile;
            this.startPos = startPos;
            this.currentWorkDir = currentWorkDir;
        }

        public void run(){
            RandomAccessFile randomAccessFile = null;
            OutputStream outputStream = null;
            try {
                randomAccessFile = new RandomAccessFile(originFile, "r");
                byte[] b = new byte[byteSize];
                randomAccessFile.seek(startPos); //移动指针到每“段”开头
                int s = randomAccessFile.read(b);
                outputStream = new FileOutputStream(currentWorkDir+fileName);
                outputStream.write(b, 0 , s);
                outputStream.flush();
                b= null;
            }catch (IOException e){
                e.printStackTrace();
            }finally {
                if (outputStream !=null){
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                if (randomAccessFile !=null){
                    try {
                        randomAccessFile.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

 

四、调用的主类StaticLargeObjectMain.java

package mian;

import largeobject.StaticLargeObject;
import base.ResultFulBase;

//静态大对象上传调用
public class StaticLargeObjectMain {

     
    public static void main(String[] args) {
        
        //连接到swift获得令牌
        ResultFulBase resultFulBase = new ResultFulBase("192.168.0.1","8080","admin:admin","admin");
        
        //初始化动态大对象的操作类
        StaticLargeObject staticLargeObject = new StaticLargeObject(resultFulBase);
        
        //上传一个动态大对象
        //注:E://1/1.zip 是一个5M多的文件, 切割大小为3M每块
        staticLargeObject.upload_Static_large_object("SegmentContainer","maniFestContainer","E://1/1.zip",  "1.zip",new Long(3) );
         
        //下载上传上去的大对象
        resultFulBase.get_container_object("maniFestContainer","1.zip","E:\\mylarge.zip");

    }

}

推荐阅读