oss上传大文件以及转码

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.model.PartETag;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSErrorCode;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CompleteMultipartUploadRequest;
import com.aliyun.oss.model.InitiateMultipartUploadRequest;
import com.aliyun.oss.model.InitiateMultipartUploadResult;
import com.aliyun.oss.model.ObjectMetadata;

/**
* @Description: 使用普通方式上传小文件,使用Multipart上传方式进行多线程分段上传较大文件
* @author: zrk
* @time: 2015年3月30日 上午10:45:12
*/
public class OSSUploadFile implements Callable{
private static final Logger logger = LoggerFactory
.getLogger(OSSUploadFile.class);

//外层线程池
public static ExecutorService uploadMainPool = null;
static{
    uploadMainPool = Executors.newFixedThreadPool(Constant.CONCURRENT_FILE_NUMBER,new ThreadFactory() {
        public Thread newThread(Runnable r) {
            Thread s = Executors.defaultThreadFactory().newThread(r);
            s.setDaemon(true);
            return s;
        }
    });
}
//内层线程池
private ExecutorService pool ;
private MultipartFile sourcePath;//原文件路径
private String bucketName;//bucketName
private String key;//云端存储路径
/**
 * oss上传 支持断点续传
 * @param sourcePath    源文件路径
 * @param bucketName    bucketName
 * @param key           存储key  -在oss的存储路径
 */
public OSSUploadFile(MultipartFile sourcePath,String bucketName,String key) {
    //实例化单文件上次线程池
    pool = Executors.newFixedThreadPool(Constant.SINGLE_FILE_CONCURRENT_THREADS);
    this.sourcePath = sourcePath;
    this.bucketName = bucketName;
    this.key = key;
}

/**
 * 执行当前线程
 * @return
 */
@SuppressWarnings("finally")
public Integer uploadFile() {
    Integer r = Global.ERROR;
     //向uploadMainPool中submit当前线程
    Future<Integer> result = uploadMainPool.submit(this);
    try {
        r=result.get();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } finally{
        return r;
    }

}


/**
 * oss上传
 * @param sourcePath    源文件路径
 * @param bucketName    bucketName
 * @param key           存储key  存储路径
 * @return Integer
 */
@Override
public Integer call(){

    OSSClient client  = OssUtil.getOSSClient();    

    //File uploadFile = new File(sourcePath);
    /*if (!sourcePath.exists()){ 

        return Global.FILE_NOT_FOUND_ERROR;
    }*/
    int result = Global.ERROR;

    key = key.contains("\\\\")?key.replaceAll("\\\\", "/"):key.contains("\\")?key.replaceAll("\\", "/"):key; 
    // 准备Bucket
    result = ensureBucket(client,bucketName);
    if(result == Global.ERROR )return result;
    // 使用multipart的方式上传文件
    result = uploadBigFile(client, bucketName, key, sourcePath);
    pool = null;
    return result;
}


// 通过Multipart的方式上传一个大文件
private int uploadBigFile(OSSClient client, String bucketName, String key,
        MultipartFile uploadFile)  {

    //自定义的每个上传分块大小
    Integer partSize = Constant.UPLOAD_PART_SIZE;

    //需要上传的文件分块数
    int partCount = calPartCount(uploadFile,partSize);

    //文件的MD5值
    String fileDM5Str = "";
    String uploadId = "";

    //序列化的文件路径(与上传文件同路径使用.up.temp后缀)

    String serializationFilePath =File.separator+ "tmp"+File.separator+"vide.mp4"+".up.temp";

    boolean isSerializationFile = false;

    //子线程池的线程对象封装类(用于序列化的)
    UploadPartObj uploadPartObj = null;
    //获取文件MD5值
    fileDM5Str = MD5Util.getFileMD5(uploadFile);

    //若存在上传失败留下的序列化文件则反序列化对象
    if(new File(serializationFilePath).exists()){
        uploadPartObj = (UploadPartObj)ObjectSerializableUtil.deserialization(serializationFilePath);
        isSerializationFile = true;
    }       

    //序列化文件不存在,分配分块给子线程池线程对象
    if(uploadPartObj==null||!isSerializationFile){
        uploadPartObj = new UploadPartObj();
        try {
            //初始化MultipartUpload 返回uploadId  
            uploadId = initMultipartUpload(client, bucketName, key,fileDM5Str);
        } catch (Exception e) {
            e.printStackTrace();

            return Global.OSS_SUBMIT_ERROR;
        } 
        for (int i = 0; i < partCount ; i++) {
            long start = partSize * i;
            long curPartSize = partSize < uploadFile.getSize() - start ?
                    partSize : uploadFile.getSize() - start;
          //构造上传线程,UploadPartThread是执行每个分块上传任务的线程

         uploadPartObj.getUploadPartThreads().add(new UploadPartThread(client, bucketName, key,uploadFile, uploadId, i + 1,partSize * i, curPartSize));
        }
    }

    try {
        int i = 0;
        //upload方法提交分块上传线程至子线程池上传,while循环用于上传失败重复上传,Constant.RETRY定义重复次数
        while (upload(uploadPartObj,serializationFilePath).isResult()==false) {
            if(++i == Constant.RETRY)break;
        }
    } catch (Exception e) {
        e.printStackTrace();

        return Global.THREAD_ERROR;
    } 

    if(!uploadPartObj.isResult()){
        return Global.NETWORK_ERROR;
    }
    try {
        //完成一个multi-part请求。
        completeMultipartUpload(client, bucketName, key, uploadPartObj);
    } catch (Exception e) {
        e.printStackTrace();
        logger.error("multi-part请求失败!!");
       ObjectSerializableUtil.serialization(uploadPartObj,serializationFilePath);
        return Global.OSS_SUBMIT_ERROR;
    }
    return Global.SUCCESS;
}

/**
 * 多线程上传单个文件
 * @param uploadPartObj
 * @param serializationFilePath
 * @return
 */
private UploadPartObj upload(UploadPartObj uploadPartObj,String serializationFilePath){

    try {

        uploadPartObj.setResult(true);

        //向子线程池中submit单个文件所有分块上传线程
        for (int i=0;i<uploadPartObj.getUploadPartThreads().size();i++) {
            if(uploadPartObj.getUploadPartThreads().get(i).getMyPartETag()==null)
                pool.submit(uploadPartObj.getUploadPartThreads().get(i));
        }

        //shutdown子线程池,池内所上传任务执行结束后停止当前线程池
        pool.shutdown();
        while (!pool.isTerminated()) {
            //循环检查线程池,同时在此序列化uploadPartObj
            ObjectSerializableUtil.serialization(uploadPartObj,serializationFilePath);
            pool.awaitTermination(Constant.SERIALIZATION_TIME, TimeUnit.SECONDS);
        }

        //判断上传结果
        for (UploadPartThread uploadPartThread: uploadPartObj.getUploadPartThreads()) {
            if(uploadPartThread.getMyPartETag()==null)
                uploadPartObj.setResult(false);

        }
        //上传成功 删除序列化文件
        if (uploadPartObj.isResult()==true) 
            ObjectSerializableUtil.delSerlzFile(serializationFilePath);
    } catch (Exception e) {
       logger.error("多线程上传单个文件异常!!");

    }
    return uploadPartObj;


}

// 根据文件的大小和每个Part的大小计算需要划分的Part个数。
private static int calPartCount(MultipartFile f,Integer partSize) {
    int partCount = (int) (f.getSize() / partSize);
    if (f.getSize() % partSize != 0){
        partCount++;
    }
    return partCount;
}

// 创建Bucket
private int ensureBucket(OSSClient client, String bucketName){
        try {
            // 创建bucket
            client.createBucket(bucketName);
            //设置bucket的访问权限,public-read-write权限
            client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
        } catch (OSSException e) {
            e.printStackTrace();

            return Global.ERROR;
        } catch (ClientException e) {
            if (!OSSErrorCode.BUCKET_ALREADY_EXISTS.equals(e.getErrorCode())) {
                // 如果Bucket已经存在,则忽略

            }else{
                e.printStackTrace();

                return Global.ERROR;
            }
        }
        return Global.SUCCESS;
}

// 初始化一个Multi-part upload请求。
private static String initMultipartUpload(OSSClient client,String bucketName, String key,String fileDM5Str) throws OSSException,ClientException{
    String uploadId=null;
   try{ 
    ObjectMetadata objectMetadata =new ObjectMetadata();
    objectMetadata.getUserMetadata().put(Global.X_OSS_META_MY_MD5,fileDM5Str);
    InitiateMultipartUploadRequest initUploadRequest = new InitiateMultipartUploadRequest(bucketName, key, objectMetadata);
    InitiateMultipartUploadResult initResult = client.initiateMultipartUpload(initUploadRequest);
    uploadId = initResult.getUploadId();

    System.err.println(uploadId);
   }catch (Exception e) {
    logger.error("初始化Multi-part upload请求失败!!");
}
    return uploadId;

}

// 完成一个multi-part请求。
private static void completeMultipartUpload(OSSClient client, String bucketName, String key,UploadPartObj uploadPartObj){
    List<PartETag> eTags = new ArrayList<PartETag>(); 
    for (UploadPartThread uploadPartThread : uploadPartObj.getUploadPartThreads()) {
        eTags.add(new PartETag(uploadPartThread.getMyPartETag().getPartNumber(),uploadPartThread.getMyPartETag().geteTag()));
    }
    //为part按partnumber排序
    Collections.sort(eTags, new Comparator<PartETag>(){
        public int compare(PartETag arg0, PartETag arg1) {
            PartETag part1= arg0;
            PartETag part2= arg1;
            return part1.getPartNumber() - part2.getPartNumber();
        }  
    });
    try{
    CompleteMultipartUploadRequest completeMultipartUploadRequest =
            new CompleteMultipartUploadRequest(bucketName, key, uploadPartObj.getUploadPartThreads().get(0).getUploadId(), eTags);
    System.err.println(uploadPartObj.getUploadPartThreads().get(0).getUploadId());
    client.completeMultipartUpload(completeMultipartUploadRequest);
    }catch (Exception e) {
        logger.error("合并上传失败!!");
    }
}

}

这里是主程序,用的文件流是MultipartFile,下面是主程序需要用到的一些类和方法。

import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;

import org.springframework.web.multipart.MultipartFile;

public class MD5Util {
public static String getFileMD5(MultipartFile file) {
/* if (!file.exists() || !file.isFile()) {
return null;
} */
MessageDigest digest = null;
InputStream in = null;
byte buffer[] = new byte[1024];
int len;
try {
digest = MessageDigest.getInstance(“MD5”);
//in = new FileInputStream(file);
in=file.getInputStream();
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
BigInteger bigInt = new BigInteger(1, digest.digest());
return bigInt.toString(16);
}

}

import java.io.Serializable;

import com.aliyun.oss.model.PartETag;

/**
* @Description: 封装PartETag 用于序列化
* @author: zrk
* @time: 2015年4月1日 上午10:52:50
*/
public class MyPartETag implements Serializable {

private static final long serialVersionUID = 1L;

private int partNumber;

private String eTag;


public MyPartETag(PartETag partETag ) {
    super();
    this.partNumber = partETag.getPartNumber();
    this.eTag = partETag.getETag();
}

public int getPartNumber() {
    return partNumber;
}

public void setPartNumber(int partNumber) {
    this.partNumber = partNumber;
}

public String geteTag() {
    return eTag;
}

public void seteTag(String eTag) {
    this.eTag = eTag;
}

}

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ObjectSerializableUtil {
public static void serialization (Object object, String serializationFilePath) {
File file = new File(serializationFilePath);
if (!new File(file.getParent()).exists())
new File(file.getParent()).mkdirs();
if (file.exists())
file.delete();
ObjectOutputStream oos = null;

try {
        oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(object);
        oos.close();
    } catch (IOException e) {
        e.printStackTrace();

        try {if (oos!=null)oos.close();} catch (IOException e1) {e1.printStackTrace();}
        file.delete();
    }
}

public static Object deserialization (String serializationFilePath) {
    File file = new File(serializationFilePath);
    if (!file.exists())
        return null;
    else {

    }
    try {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        Object object = ois.readObject();
        ois.close();
        file.delete();
        return object;
    } catch (Exception e) {

        return null;
    }
}

public static boolean delSerlzFile(String serializationFilePath) {
    File file = new File(serializationFilePath);
    if (file.exists())
        return file.delete();
    return true;
}

}

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* 单个文件的上传线程集合
* @Description: TODO
* @author: zrk
* @time: 2015年5月6日 下午1:56:54
*/
public class UploadPartObj implements Serializable{

private static final long serialVersionUID = 1L;

List<UploadPartThread> uploadPartThreads = Collections.synchronizedList(new ArrayList<UploadPartThread>());

boolean result = true;

public List<UploadPartThread> getUploadPartThreads() {
    return uploadPartThreads;
}
public void setUploadPartThreads(List<UploadPartThread> uploadPartThreads) {
    this.uploadPartThreads = uploadPartThreads;
}
public boolean isResult() {
    return result;
}
public void setResult(boolean result) {
    this.result = result;
}

}

import java.io.InputStream;
import java.io.Serializable;
import java.util.concurrent.Callable;

import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.model.UploadPartResult;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.UploadPartRequest;

/**
* @Description: 上传每个part的线程类 可序列化 用于上传的断点续传
* @author: zrk
* @time: 2015年4月1日 上午10:35:34
*/
public class UploadPartThread implements Callable ,Serializable {

private static final long serialVersionUID = 1L;

private MultipartFile uploadFile;
private String bucket;
private String object;
private long start;
private long size;
private int partId;
private String uploadId;

private MyPartETag myPartETag; 

public UploadPartThread(OSSClient client,String bucket, String object,
        MultipartFile uploadFile,String uploadId, int partId,
        long start, long partSize) {
    this.uploadFile = uploadFile;
    this.bucket = bucket;
    this.object = object;
    this.start = start;
    this.size = partSize; 
    this.partId = partId;
    this.uploadId = uploadId;
}

@SuppressWarnings("finally")
@Override
public UploadPartThread call() {

    InputStream in = null;
    try {
        //in = new FileInputStream(uploadFile);
        in=uploadFile.getInputStream();
        in.skip(start);

        UploadPartRequest uploadPartRequest = new UploadPartRequest();
        uploadPartRequest.setBucketName(bucket);
        uploadPartRequest.setKey(object);
        uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setInputStream(in);
        uploadPartRequest.setPartSize(size);
        uploadPartRequest.setPartNumber(partId);
        //MyPartETag是对uploadPartResult.getPartETag()的返回值PartETag的封装,主要是为了能序列化PartETag,MyPartETag仅比PartETag多实现了Serializable接口
        UploadPartResult uploadPartResult = OssUtil.getOSSClient().uploadPart(uploadPartRequest); 
        myPartETag = new MyPartETag(uploadPartResult.getPartETag());
    } catch (Exception e) {
        e.printStackTrace();

    } finally {
        if (in != null){
            try {
                in.close();
            } catch (final Exception e) {

            }
        }
        return this;
    }
}

public String getUploadId() {
    return uploadId;
}

public void setUploadId(String uploadId) {
    this.uploadId = uploadId;
}

public MyPartETag getMyPartETag() {
    return myPartETag;
}

public void setMyPartETag(MyPartETag myPartETag) {
    this.myPartETag = myPartETag;
}

}

下面的代码是获取oss对象和简单上传小文件及一个单线程的分片断点续传。
import java.io.FileInputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CompleteMultipartUploadRequest;
import com.aliyun.oss.model.CompleteMultipartUploadResult;
import com.aliyun.oss.model.InitiateMultipartUploadRequest;
import com.aliyun.oss.model.InitiateMultipartUploadResult;
import com.aliyun.oss.model.ListMultipartUploadsRequest;
import com.aliyun.oss.model.ListPartsRequest;
import com.aliyun.oss.model.MultipartUpload;
import com.aliyun.oss.model.MultipartUploadListing;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PartETag;
import com.aliyun.oss.model.PartListing;
import com.aliyun.oss.model.PartSummary;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyun.oss.model.UploadPartRequest;
import com.aliyun.oss.model.UploadPartResult;

public class OssUtil {

// 阿里云API的内或外网域名
private static String ENDPOINT;
// 阿里云API的密钥Access Key ID
private static String ACCESS_KEY_ID;
// 阿里云API的密钥Access Key Secret
private static String ACCESS_KEY_SECRET;

// init static datas
static {
    ResourceBundle bundle = PropertyResourceBundle.getBundle("oss");
    ENDPOINT = bundle.getString("endpoint").trim();
    int a = ENDPOINT.length();
    System.err.println("a=" + a);
    ACCESS_KEY_ID = bundle.getString("accessKeyId").trim();
    int b = ACCESS_KEY_ID.length();
    System.err.println("b=" + b);
    ACCESS_KEY_SECRET = bundle.getString("accessKeySecret").trim();
    int c = ACCESS_KEY_SECRET.length();
    System.err.println("c=" + c);
}

/**
 * 获取阿里云OSS客户端对象
 * */
public static OSSClient getOSSClient() {
    OSSClient ocClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID,
            ACCESS_KEY_SECRET);
    return ocClient;
}

/**
 * 上传图片至OSS
 * 
 * @param ossClient
 *            oss连接
 * @param file
 *            上传文件(文件全路径如:D:\\image\\cake.jpg)
 * @param bucketName
 *            存储空间
 * @param folder
 *            模拟文件夹名 如"qj_nanjing/"
 * @return String 返回的唯一MD5数字签名
 * */
public static String uploadObject2OSS(OSSClient ossClient,
        MultipartFile file, String bucketName, String folder,
        String fileName) {
    String resultStr = null;
    try {
        // 以输入流的形式上传文件
        // InputStream is = new FileInputStream(file);
        // 文件名
        // String fileName = file.getOriginalFilename();
        // 文件大小
        // Long fileSize = file.length();
        // 创建上传Object的Metadata
        ObjectMetadata metadata = new ObjectMetadata();
        // 上传的文件的长度
        metadata.setContentLength(file.getSize());
        // 指定该Object被下载时的网页的缓存行为
        metadata.setCacheControl("no-cache");
        // 指定该Object下设置Header
        metadata.setHeader("Pragma", "no-cache");
        // 指定该Object被下载时的内容编码格式
        metadata.setContentEncoding("utf-8");
        // 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,
        // 如果没有扩展名则填默认值application/octet-stream
        // metadata.setContentType(getContentType(fileName));
        // 指定该Object被下载时的名称(指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称)
        // metadata.setContentDisposition("filename/filesize=" + fileName
        // + "/" + fileSize + "Byte.");
        // 上传文件 (上传文件流的形式)
        PutObjectResult putResult = ossClient.putObject(bucketName, folder
                + fileName, file.getInputStream(), metadata);
        // 解析结果
        resultStr = putResult.getETag();
    } catch (Exception e) {
        e.printStackTrace();

    }

    return resultStr;
}

/**
 * 通过文件名判断并获取OSS服务文件上传时文件的contentType
 * 
 * @param fileName
 *            文件名
 * @return 文件的contentType
 */
public static String getContentType(String fileName) {
    // 文件的后缀名
    String fileExtension = fileName.substring(fileName.lastIndexOf("."));
    if (".bmp".equalsIgnoreCase(fileExtension)) {
        return "image/bmp";
    }
    if (".gif".equalsIgnoreCase(fileExtension)) {
        return "image/gif";
    }
    if (".jpeg".equalsIgnoreCase(fileExtension)
            || ".jpg".equalsIgnoreCase(fileExtension)
            || ".png".equalsIgnoreCase(fileExtension)) {
        return "image/jpeg";
    }
    if (".html".equalsIgnoreCase(fileExtension)) {
        return "text/html";
    }
    if (".txt".equalsIgnoreCase(fileExtension)) {
        return "text/plain";
    }
    if (".vsd".equalsIgnoreCase(fileExtension)) {
        return "application/vnd.visio";
    }
    if (".ppt".equalsIgnoreCase(fileExtension)
            || "pptx".equalsIgnoreCase(fileExtension)) {
        return "application/vnd.ms-powerpoint";
    }
    if (".doc".equalsIgnoreCase(fileExtension)
            || "docx".equalsIgnoreCase(fileExtension)) {
        return "application/msword";
    }
    if (".xml".equalsIgnoreCase(fileExtension)) {
        return "text/xml";
    }
    // 默认返回类型
    return "image/jpeg";
}

/**
 * 获得url链接
 * 
 * @param key
 * @return
 */
public static String getUrl(String key) {
    // 设置URL过期时间为10年 3600l* 1000*24*365*10
    Date expiration = new Date(new Date().getTime() + 3600l * 1000 * 24
            * 365 * 10);
    // 生成URL
    // 初始化OSSClient
    OSSClient ossClient = OssUtil.getOSSClient();
    URL url = ossClient.generatePresignedUrl("fsg-video", key, expiration);
    if (url != null) {
        return url.toString();
    }
    return null;

}

/**
 * 断点续传
 * 
 * @param key
 * @return
 */
public static String multipartUploadObject(String bucketName, String key,
        MultipartFile    partFile) {
    String tag = null;
    String uploadid = null;
    int j = 0;
    // 初始化一个OSSClient
    OSSClient client = getOSSClient();
    ListMultipartUploadsRequest lmur = new ListMultipartUploadsRequest(
            bucketName);

    // 获取Bucket内所有上传事件
    MultipartUploadListing listing = client.listMultipartUploads(lmur);
    // 新建一个List保存每个分块上传后的ETag和PartNumber
    List<PartETag> partETags = new ArrayList<PartETag>();

    // 遍历所有上传事件 设置UploadId
    for (MultipartUpload multipartUpload : listing.getMultipartUploads()) {
        if (multipartUpload.getKey().equals(key)) {
            uploadid = multipartUpload.getUploadId();
            break;
        }
    }

    if (StringUtils.isEmpty(uploadid)) {
        // 开始Multipart Upload,InitiateMultipartUploadRequest
        // 来指定上传Object的名字和所属Bucke
        InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(
                bucketName, key);
        InitiateMultipartUploadResult initiateMultipartUploadResult = client
                .initiateMultipartUpload(initiateMultipartUploadRequest);
        uploadid = initiateMultipartUploadResult.getUploadId();
    } else {
        ListPartsRequest listPartsRequest = new ListPartsRequest(
                bucketName, key, uploadid);
        // listParts 方法获取某个上传事件所有已上传的块
        PartListing partListing = client.listParts(listPartsRequest);
        // 遍历所有Part
        for (PartSummary part : partListing.getParts()) {
            partETags
                    .add(new PartETag(part.getPartNumber(), part.getETag()));
            j++;
        }
    }
    // 设置每块为 5M(最小支持5M)
    final int partSize = 1024 * 1024 * 10;

    try {

        // 计算分块数目
        int partCount = (int) (partFile.getSize() / partSize);
        if (partFile.getSize() % partSize != 0) {
            partCount++;
        }

        for (int i = j; i < partCount; i++) {
            // 获取文件流
             FileInputStream fis;
             fis = (FileInputStream) partFile.getInputStream();

            // 跳到每个分块的开头
            long skipBytes = partSize * i;
            fis.skip(skipBytes);

            // 计算每个分块的大小
            long size = partSize < partFile.getSize() - skipBytes ? partSize
                    : partFile.getSize() - skipBytes;

            // 创建UploadPartRequest,上传分块
            UploadPartRequest uploadPartRequest = new UploadPartRequest();
            uploadPartRequest.setBucketName(bucketName);
            uploadPartRequest.setKey(key);
            uploadPartRequest.setUploadId(uploadid);
            uploadPartRequest.setInputStream(fis);
            uploadPartRequest.setPartSize(size);
            uploadPartRequest.setPartNumber(i + 1);

            UploadPartResult uploadPartResult = client
                    .uploadPart(uploadPartRequest);


            // 将返回的PartETag保存到List中。
            partETags.add(uploadPartResult.getPartETag());

            // 关闭文件
            fis.close();

        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
            bucketName, key, uploadid, partETags);


    // 完成分块上传
    CompleteMultipartUploadResult completeMultipartUploadResult = client
            .completeMultipartUpload(completeMultipartUploadRequest);

    // 打印Object的ETag(返回的ETag不是md5.具体是什么不详)
    tag = completeMultipartUploadResult.getETag();
    return tag;
}

}

上传完成了在说一下我在项目中遇见的问题吧,应为这个是分片上传的所以要等分片上传完了才能把分片合成一个完整的视频,这样坑就来了,本来上传一个500多M的视频就要不少时间在加上传完后还要合并碎片也要不少时间,这样就会导致这个接口超时,自己在本地测试的时候并不会报超时,但部署到线上就会出现这个问题,后来发现是负载均衡的问题,因为是用的阿里云的一站式解决方案,后来也没有什么好的解决方案,我们只好不经过负载均衡了直接访问的,这样才解决了这一问题。

好了下面给出转码的代码

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.mts.model.v20140618.SubmitJobsRequest;
import com.aliyuncs.mts.model.v20140618.SubmitJobsResponse;
import com.aliyuncs.profile.DefaultProfile;

public class OSSMTSUtil {
private static final String MTS_REGION = “cn-beijing”;
private static final String OSS_REGION = “oss-cn-beijing”;

private static final String mtsEndpoint = "mts.cn-beijing.aliyuncs.com";

private static String waterMarkFilePath = "";// 水印图片的key

private static String accessKeyId = "";
private static String accessKeySecret = "";
private static String pipelineId = "";// 转码管道ID
private static String transcodeTemplateId = "S00000001-200030";// 预制模板MP4高清
// private static String waterMarkTemplateId = "";//自定义水印模板ID


private static String Bucket = ""; // 存储空间名

private static DefaultAcsClient aliyunClient;
private static final Logger logger = LoggerFactory
.getLogger(OSSMTSUtil.class);
static {
    //添加多地区
    try {
        DefaultProfile.addEndpoint(MTS_REGION, MTS_REGION, "Mts", mtsEndpoint);
    } catch (ClientException e) {
        logger.error("多地区添加失败!!");
        e.printStackTrace();
    }
    //获取转码连接对象
    aliyunClient = new DefaultAcsClient(DefaultProfile.getProfile(
            MTS_REGION, accessKeyId, accessKeySecret));


}
/*
 * 
 * 
 * 
 */

  //提交转码作业
public static String submitTranscodeJob(OSSFileDO inputFile,
        OSSFileDO watermarkFile,String MTSFlieName) {
    /*JSONObject waterMarkConfig = new JSONObject();
    waterMarkConfig.put("InputFile", watermarkFile.toJson());
    waterMarkConfig.put("WaterMarkTemplateId", waterMarkTemplateId);
    JSONArray waterMarkConfigArray = new JSONArray();
    waterMarkConfigArray.add(waterMarkConfig);*/

    JSONObject jobConfig = new JSONObject();
    jobConfig.put("OutputObject", MTSFlieName);
    jobConfig.put("TemplateId", transcodeTemplateId);
//  jobConfig.put("WaterMarks", waterMarkConfigArray);
    JSONArray jobConfigArray = new JSONArray();
    jobConfigArray.add(jobConfig);

    SubmitJobsRequest request = new SubmitJobsRequest();

    request.setInput(inputFile.toJson().toJSONString());
    request.setOutputBucket(Bucket);
    request.setOutputs(jobConfigArray.toJSONString());
    request.setPipelineId(pipelineId);
    request.setOutputLocation(OSS_REGION);

    Integer outputJobCount = 1;

    SubmitJobsResponse response = null;
    try {
        //发送转码请求
        response = aliyunClient.getAcsResponse(request);
        if (response.getJobResultList().size() != outputJobCount) {
            throw new RuntimeException("SubmitJobsRequest Size failed");
        }

        return response.getJobResultList().get(0).getJob().getJobId();
    } catch (ServerException e) {
        logger.error("转码请求提交失败!!");
        throw new RuntimeException("submitTranscodeJob Server failed");
    } catch (ClientException e) {
        logger.error("转码请求提交失败!!");
        throw new RuntimeException("submitTranscodeJob Client failed");
    }
}

}

import com.alibaba.fastjson.JSONObject;

public class OSSFileDO {
public void setBucket(String bucket) {
this.bucket = bucket;
}

public void setObject(String object) {
    this.object = object;
}

public void setLocation(String location) {
    this.location = location;
}

public String toJsonString(){
    return toJson().toJSONString();
}

public JSONObject toJson(){
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("Bucket", bucket);
    jsonObject.put("Location", location);
    jsonObject.put("Object", object);

    return jsonObject;
}

public OSSFileDO(){

}

public OSSFileDO(String location, String bucket, String object){
    this.location = location;
    this.bucket = bucket;
    this.object = object;
}

private String location;
private String bucket;
private String object;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微笑点燃希望

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值