文件上传

在NOS中,用户的每个文件都是一个Object(对象)。

NOS提供两种文件上传方式:普通上传(PutObject),上传小于或等于100M的文件;分块上传(MultiUpload),大文件可以采用该方式上传。

AWS Java SDK提供了丰富的文件上传接口与功能,主要有:

  • 直接内容上传
  • 本地文件普通上传
  • 支持上传文件时设置文件元数据信息
  • 流式上传
  • 分块上传

下述除了分块上传不能直接使用加密client替换外,其他的都是可以直接替换使用

直接内容上传

对于一些简单的字符串内容,可以使用putObject进行上传。代码示例如下:

//要上传文件的路径
String content = "Object content";
try {
   s3Client.putObject("your-bucketname","your-objectname",content);
}catch (Exception e){
   System.out.println(e.getMessage());
}

本地文件普通上传

对于小对象可以使用putObject接口进行上传,putObject上传支持的最大文件大小为100M,如果上传大于100M的文件需要使用分块上传。本地文件普通上传的示例代码如下:

//要上传文件的路径
String filePath = "your-local-file-path";
try {
   s3Client.putObject("your-bucketname","your-objectname", new File(filePath));
}catch (Exception e){
   System.out.println(e.getMessage());
}

上传文件时设置文件元数据信息

您可以在上传文件时设置文件元数据信息。可以设置的元数据主要有文件的Content-Type和用户自定义元数据信息。 这里以普通上传为例:

String filePath = "your-local-file-path";
ObjectMetadata objectMetadata = new ObjectMetadata();
//设置Content-Type
objectMetadata.setContentType("application/xml");
//设置标准http消息头(元数据)
objectMetadata.setHeader("Cache-Control", "no-cache");
//设置用户自定义元数据信息
Map<String, String> userMeta = new HashMap<String, String>();
userMeta.put("ud", "test");
objectMetadata.setUserMetadata(userMeta);
PutObjectRequest putObjectRequest = new PutObjectRequest("your-bucketname","your-objectname", new File(filePath));
putObjectRequest.setMetadata(objectMetadata);
s3Client.putObject(putObjectRequest);

流式上传

try {
   ObjectMetadata objectMetadata = new ObjectMetadata();
   //设置流的长度,您还可以设置其他文件元数据信息
   objectMetadata.setContentLength(streamLength);
   s3Client.putObject("your-bucketname","your-objectname", inputStream, objectMetadata)
}catch (Exception e){
   System.out.println(e.getMessage());
}

分块上传

对于大于100M的对象必须进行分块上传,分块上传的最小单位单位为16K,最后一块可以小于16K,最大单位为100M,较大文件使用分块上传失败的代价比较小,只需要重新上传失败的分块即可; 在文件已经全部存在情况下可以进行分块并发上传。

初始化分块上传

 //初始化一个分块上传,获取分块上传ID,桶名 + 对像名 + 分块上传ID 唯一确定一个分块上传
 is = new FileInputStream("youFilePath");
 InitiateMultipartUploadRequest  initRequest = new InitiateMultipartUploadRequest("your-bucketname", "your-objectname");
 //您还可以在初始化分块上传时,设置文件的Content-Type
 ObjectMetadata objectMetadata = new ObjectMetadata();
 objectMetadata.setContentType("application/xml");
 initRequest.setObjectMetadata(objectMetadata);
 InitiateMultipartUploadResult initResult = s3Client.initiateMultipartUpload(initRequest);
 String uploadId = initResult.getUploadId();

进行分块上传

下面是顺序上传所有分块的示例,您也可以进行并发上传。

long filePosition = 0;
for (int i = 1; filePosition < contentLength; i++) {
    // Last part can be less than 5 MB. Adjust part size.
    partSize = Math.min(partSize, (contentLength - filePosition));
    // Create request to upload a part.
    UploadPartRequest uploadRequest = new UploadPartRequest()
            .withBucketName(bucketName).withKey(key)
            .withUploadId(uploadId).withPartNumber(i)
            .withFileOffset(filePosition)
            .withFile(file) //要上传的文件对象
            .withPartSize(partSize);
    //如果是加密的,需要加入这步
    if (filePosition + partSize == contentLength){
        uploadRequest.setLastPart(true);
    }
    // Upload part and add response to our list.
    partETags.add(encryptionClient.uploadPart(uploadRequest).getPartETag());

    ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, key, initResponse.getUploadId());
    encryptionClient.listParts(listPartsRequest);

    filePosition += partSize;
}

列出所有分块

 //这里可以检查分块是否全部上传,分块MD5是否与本地计算相符,如果不符或者缺少可以重新上传

 List<PartETag> partETags = new ArrayList<PartETag>();

 int nextMarker = 0;
 while (true) {
    ListPartsRequest listPartsRequest = new ListPartsRequest("your-bucketname", 
                                                  "your-objectname", uploadId);
    listPartsRequest.setPartNumberMarker(nextMarker);

    PartListing partList = s3Client.listParts(listPartsRequest);

    for (PartSummary ps : partList.getParts()) {
        nextMarker++;
        partETags.add(new PartETag(ps.getPartNumber(), ps.getETag()));
    }

    if (!partList.isTruncated()) {
        break;
    }
 }

完成分块上传

CompleteMultipartUploadRequest completeRequest =  new CompleteMultipartUploadRequest(
                          "your-bucketname","your-objectname", uploadId, partETags);
CompleteMultipartUploadResult completeResult = s3Client.completeMultipartUpload(completeRequest);

取消分块上传

s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(
                bucketName, key, initResponse.getUploadId()));