All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ksyun.ks3.service.request.UploadPartRequest Maven / Gradle / Ivy

package com.ksyun.ks3.service.request;

import static com.ksyun.ks3.exception.client.ClientIllegalArgumentExceptionGenerator.between;
import static com.ksyun.ks3.exception.client.ClientIllegalArgumentExceptionGenerator.notNull;
import static com.ksyun.ks3.exception.client.ClientIllegalArgumentExceptionGenerator.notNullInCondition;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ksyun.ks3.InputSubStream;
import com.ksyun.ks3.LengthCheckInputStream;
import com.ksyun.ks3.RepeatableFileInputStream;
import com.ksyun.ks3.config.Constants;
import com.ksyun.ks3.dto.SSECustomerKey;
import com.ksyun.ks3.exception.client.ClientFileNotFoundException;
import com.ksyun.ks3.http.HttpHeaders;
import com.ksyun.ks3.http.HttpMethod;
import com.ksyun.ks3.http.Request;
import com.ksyun.ks3.utils.HttpUtils;
import com.ksyun.ks3.utils.StringUtils;

/**
 * @author lijunwei[[email protected]]  
 * 
 * @date 2014年10月23日 上午11:17:36
 * 
 * @description 分块上传时,Upload Part的请求
 *              

* 可以通过setContentMD5()指定MD5值,使其在服务端进行md5值校验,否则只会在客户端校验(区别: * 前者校验失败不会上传成功) *

*

* 支持提供文件对象进行分块上传,请使用UploadPartRequest(String bucketname, String * objectkey, String uploadId, int partNumber, File file, long * partsize, long fileoffset) *

*

* 支持提供已经切分好的流进行分块上传,请提供流的长度,请使用 UploadPartRequest(String * bucketname, String objectkey, String uploadId, int partNumber, * InputStream content, long partSize) *

* **/ public class UploadPartRequest extends Ks3WebServiceRequest implements SSECustomerKeyRequest{ private static final Log log = LogFactory.getLog(UploadPartRequest.class); private String bucket; private String key; /** * 由init multipart upload获取到的uploadId */ private String uploadId; /** * 分块上传时对块的编号,1-10000,请保证partNumber是连续的 */ private int partNumber; /** * 要上传的文件 */ private File file; /** * 要上传的数据流 */ private InputStream inputStream; /** * 当前块的大小,文件的时候最后一块大小不一定要准确,但是流的时候需要准确 */ private long partSize; /** * 文件的时候,之前已经读取的数据量 */ private long fileoffset; /** * 是否为最后一块,客户端数据加密时需要指定该值 */ private boolean lastPart = false; /** * 使用用户指定的key进行服务端加密 */ private SSECustomerKey sseCustomerKey; /** * 要上传的内容的MD5值 */ private String ContentMD5; public UploadPartRequest(String bucketname,String objectkey){ this.bucket = bucketname; this.key = objectkey; } /** * * @param bucketname * @param objectkey * @param uploadId * @param partNumber * @param file * @param partsize * 注意类型为long,块的大小,除最后一块外需要给准确数字。必须提供,最大为5G,除最后一块最小为5M。当总大小小于5M,每块的最小值为100K * @param fileoffset * 注意类型为long,文件中已被读取的量 */ public UploadPartRequest(String bucketname, String objectkey, String uploadId, int partNumber, File file, long partsize, long fileoffset) { this.bucket = bucketname; this.key = objectkey; this.setUploadId(uploadId); this.setPartNumber(partNumber); this.setFile(file); this.partSize = partsize; this.setFileoffset(fileoffset); if(file.length() - fileoffset <= this.partSize){ this.setLastPart(true); } } /** * * @param bucketname * @param objectkey * @param uploadId * @param partNumber * @param content * 要上传的块的inputstream,(已经切分好的块) * @param partSize * content的长度,必须提供,最大为5G,除最后一块最小为5M。当总大小小于5M,每块的最小值为100K */ public UploadPartRequest(String bucketname, String objectkey, String uploadId, int partNumber, InputStream content, long partSize) { this.bucket = bucketname; this.key = objectkey; this.setUploadId(uploadId); this.setPartNumber(partNumber); this.setPartSize(partSize); this.inputStream = content; } @Override public void validateParams() throws IllegalArgumentException { if (StringUtils.isBlank(this.bucket)) throw notNull("bucketname"); if (StringUtils.isBlank(this.key)) throw notNull("objectkey"); if (StringUtils.isBlank(this.uploadId)) throw notNull("uploadId"); if (partNumber < Constants.minPartNumber || partNumber > Constants.maxPartNumber) throw between("partNumber",String.valueOf(this.partNumber),String.valueOf(Constants.minPartNumber),String.valueOf(Constants.maxPartNumber)); if (file == null && this.inputStream == null) { throw notNull( "file(file to upload)","inputStream(inputStream to upload)"); } else { if (file != null) { if (this.fileoffset < 0||this.fileoffset>file.length()) throw between("fileoffset",String.valueOf(this.fileoffset),"0", String.valueOf(file.length())); }else{ if(this.partSize <= 0l) throw notNullInCondition("partSize","upload part by inputstream"); } } if (this.partSize > Constants.maxPartSize||this.partSize==0) { throw between("partsize",String.valueOf(this.partSize),"1", String.valueOf(Constants.maxPartSize)); } } public String getBucket() { return bucket; } public void setBucket(String bucket) { this.bucket = bucket; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public InputStream getInputStream() { return inputStream; } public void setInputStream(InputStream inputStream) { this.inputStream = inputStream; } public String getUploadId() { return uploadId; } public void setUploadId(String uploadId) { this.uploadId = uploadId; } public int getPartNumber() { return partNumber; } public void setPartNumber(int partNumber) { this.partNumber = partNumber; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } public long getPartSize() { return partSize; } /** * 获取实际的大小 * @return */ public long getInstancePartSize() { if(this.file!=null){ long truesize = file.length() - fileoffset < this.partSize ? file.length() - fileoffset : this.partSize; return truesize; }else{ return partSize; } } public void setPartSize(long partSize) { this.partSize = partSize; } public long getFileoffset() { return fileoffset; } public void setFileoffset(long fileoffset) { this.fileoffset = fileoffset; } public boolean isLastPart() { return lastPart; } public void setLastPart(boolean lastPart) { this.lastPart = lastPart; } public SSECustomerKey getSseCustomerKey() { return sseCustomerKey; } public void setSseCustomerKey(SSECustomerKey sseCustomerKey) { this.sseCustomerKey = sseCustomerKey; } @Override public void buildRequest(Request request) { request.setMethod(HttpMethod.PUT); request.setBucket(bucket); request.setKey(key); request.addHeader(HttpHeaders.ContentType, "application/octet-stream"); request.addQueryParam("uploadId", this.uploadId); request.addQueryParam("partNumber", String.valueOf(this.partNumber)); if (this.file != null) { long truesize = getInstancePartSize(); if(file.length() - fileoffset <= this.partSize){ this.setLastPart(true); } try { //文件流并没有复用,closeSourceStream需要置为true,否则文件句柄未释放 request.setContent(new LengthCheckInputStream(new InputSubStream(new RepeatableFileInputStream( this.file), this.fileoffset, truesize, true),truesize,true)); } catch (FileNotFoundException e) { throw new ClientFileNotFoundException(e); } }else{ request.setContent(new LengthCheckInputStream(inputStream,this.partSize,true)); } //添加服务端加密相关 request.getHeaders().putAll(HttpUtils.convertSSECustomerKey2Headers(sseCustomerKey)); request.addHeader(HttpHeaders.ContentLength, String.valueOf(this.getInstancePartSize())); if(!StringUtils.isBlank(ContentMD5)){ request.addHeader(HttpHeaders.ContentMD5, ContentMD5); } } public String getContentMD5() { return ContentMD5; } public void setContentMD5(String contentMD5) { ContentMD5 = contentMD5; } @Override public void onFinally(){ if(this.inputStream != null){ try{ inputStream.close(); }catch(Exception e){ log.error("put object on finally close input stream err,"+e.getMessage()); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy