diff --git a/src/main/java/com/aliyun/oss/internal/OSSDownloadOperation.java b/src/main/java/com/aliyun/oss/internal/OSSDownloadOperation.java index b4fe9afb..7a235000 100644 --- a/src/main/java/com/aliyun/oss/internal/OSSDownloadOperation.java +++ b/src/main/java/com/aliyun/oss/internal/OSSDownloadOperation.java @@ -49,6 +49,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import com.aliyun.oss.ClientException; import com.aliyun.oss.InconsistentException; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.common.utils.CRC64; @@ -539,11 +540,13 @@ private DownloadResult download(DownloadCheckPoint downloadCheckPoint, DownloadF ProgressPublisher.publishResponseBytesTransferred(listener, completedLength); downloadFileRequest.setProgressListener(null); + SimplifiedObjectMeta meta = objectOperation.getSimplifiedObjectMeta(new GenericRequest(downloadFileRequest.getBucketName(), downloadFileRequest.getKey())); + // Concurrently download parts. for (int i = 0; i < downloadCheckPoint.downloadParts.size(); i++) { if (!downloadCheckPoint.downloadParts.get(i).isCompleted) { Task task = new Task(i, "download-" + i, downloadCheckPoint, i, downloadFileRequest, objectOperation, - listener); + listener, meta); futures.add(service.submit(task)); tasks.add(task); } else { @@ -592,7 +595,7 @@ class Task implements Callable { public Task(int id, String name, DownloadCheckPoint downloadCheckPoint, int partIndex, DownloadFileRequest downloadFileRequest, OSSObjectOperation objectOperation, - ProgressListener progressListener) { + ProgressListener progressListener, SimplifiedObjectMeta simplifiedMeta) { this.id = id; this.name = name; this.downloadCheckPoint = downloadCheckPoint; @@ -600,6 +603,7 @@ public Task(int id, String name, DownloadCheckPoint downloadCheckPoint, int part this.downloadFileRequest = downloadFileRequest; this.objectOperation = objectOperation; this.progressListener = progressListener; + this.simplifiedMeta = simplifiedMeta; } @Override @@ -643,6 +647,8 @@ public PartResult call() throws Exception { objectMetadata = ossObj.getObjectMetadata(); content = ossObj.getObjectContent(); + this.verifyObjectMeta(ossObj, getObjectRequest, simplifiedMeta); + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; int bytesRead = 0; while ((bytesRead = IOUtils.readNBytes(content, buffer, 0, buffer.length)) > 0) { @@ -680,6 +686,29 @@ public PartResult call() throws Exception { return tr; } + public void verifyObjectMeta(OSSObject ossObj, GetObjectRequest getObjectRequest, SimplifiedObjectMeta simplifiedMeta) { + if(ossObj.getResponse().getStatusCode() == 206){ + long rangeSetStart = getObjectRequest.getRange()[0]; + + String returnSet = ossObj.getResponse().getHeaders().get("Content-Range"); + String returnStartStr = returnSet.substring(returnSet.indexOf("bytes")+6,(returnSet.indexOf("-"))); + Long returnSetStart = -1L; + try { + returnSetStart = Long.parseLong(returnStartStr); + } catch(Exception e){ + logException("Failed to convert string to long", e); + } + + if(rangeSetStart != returnSetStart){ + throw new ClientException("Range get fail, expect offset:" + getObjectRequest.getRange() + "return offset:" + returnSet); + } + } + + if(simplifiedMeta.getLastModified().hashCode() != ossObj.getObjectMetadata().getLastModified().hashCode()){ + throw new ClientException("The last modification time of the file has changed, Last file modification time:" + ossObj.getObjectMetadata().getLastModified() + ", The file modification time:" + simplifiedMeta.getLastModified()); + } + } + public ObjectMetadata GetobjectMetadata() { return objectMetadata; } @@ -692,6 +721,7 @@ public ObjectMetadata GetobjectMetadata() { private OSSObjectOperation objectOperation; private ObjectMetadata objectMetadata; private ProgressListener progressListener; + private SimplifiedObjectMeta simplifiedMeta; } private ArrayList splitFile(long start, long objectSize, long partSize) { diff --git a/src/main/java/com/aliyun/oss/internal/OSSUploadOperation.java b/src/main/java/com/aliyun/oss/internal/OSSUploadOperation.java index ddb928b2..f65f3b6a 100644 --- a/src/main/java/com/aliyun/oss/internal/OSSUploadOperation.java +++ b/src/main/java/com/aliyun/oss/internal/OSSUploadOperation.java @@ -51,18 +51,7 @@ import com.aliyun.oss.event.ProgressEventType; import com.aliyun.oss.event.ProgressListener; import com.aliyun.oss.event.ProgressPublisher; -import com.aliyun.oss.model.CannedAccessControlList; -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.ObjectMetadata; -import com.aliyun.oss.model.PartETag; -import com.aliyun.oss.model.Payer; -import com.aliyun.oss.model.UploadFileRequest; -import com.aliyun.oss.model.UploadFileResult; -import com.aliyun.oss.model.UploadPartRequest; -import com.aliyun.oss.model.UploadPartResult; +import com.aliyun.oss.model.*; /** * OSSUploadOperation @@ -477,11 +466,12 @@ private ArrayList upload(UploadCheckPoint uploadCheckPoint, UploadFi ProgressPublisher.publishRequestBytesTransferred(listener, completedLength); uploadFileRequest.setProgressListener(null); + File file = new File(uploadCheckPoint.uploadFile); // Upload parts. for (int i = 0; i < uploadCheckPoint.uploadParts.size(); i++) { if (!uploadCheckPoint.uploadParts.get(i).isCompleted) { futures.add(service.submit(new Task(i, "upload-" + i, uploadCheckPoint, i, uploadFileRequest, - multipartOperation, listener))); + multipartOperation, listener, file.lastModified()))); } else { taskResults.add(new PartResult(i + 1, uploadCheckPoint.uploadParts.get(i).offset, uploadCheckPoint.uploadParts.get(i).size, uploadCheckPoint.uploadParts.get(i).crc)); @@ -517,7 +507,7 @@ class Task implements Callable { public Task(int id, String name, UploadCheckPoint uploadCheckPoint, int partIndex, UploadFileRequest uploadFileRequest, OSSMultipartOperation multipartOperation, - ProgressListener progressListener) { + ProgressListener progressListener, long lastModified) { this.id = id; this.name = name; this.uploadCheckPoint = uploadCheckPoint; @@ -525,6 +515,7 @@ public Task(int id, String name, UploadCheckPoint uploadCheckPoint, int partInde this.uploadFileRequest = uploadFileRequest; this.multipartOperation = multipartOperation; this.progressListener = progressListener; + this.lastModified = lastModified; } @Override @@ -532,6 +523,8 @@ public PartResult call() throws Exception { PartResult tr = null; InputStream instream = null; + File file = new File(uploadCheckPoint.uploadFile); + this.verifyObjectMeta(lastModified, file.lastModified()); try { UploadPart uploadPart = uploadCheckPoint.uploadParts.get(partIndex); tr = new PartResult(partIndex + 1, uploadPart.offset, uploadPart.size); @@ -584,6 +577,12 @@ public PartResult call() throws Exception { return tr; } + public void verifyObjectMeta(long lastModified, long currentLastModified) { + if(lastModified != currentLastModified){ + throw new ClientException("The last modification time of the file has changed, Last file modification time:" + currentLastModified + ", The file modification time:" + lastModified); + } + } + private int id; private String name; private UploadCheckPoint uploadCheckPoint; @@ -591,6 +590,7 @@ public PartResult call() throws Exception { private UploadFileRequest uploadFileRequest; private OSSMultipartOperation multipartOperation; private ProgressListener progressListener; + private long lastModified; } private CompleteMultipartUploadResult complete(UploadCheckPoint uploadCheckPoint,