繁体   English   中英

使用 AWS Java S3 SDK TransferManager 从 SFTP 流恢复上传

[英]Using AWS Java S3 SDK TransferManager to resume an upload from a SFTP stream

目前,我正在使用 Java 的 S3 SDK 中的 AWS 的 TransferManager 触发从 SFTP 服务器到 S3 的上传。 我触发此上传的方式如下:

(伪代码...)

    @Autowired
    TransferManager transferManager;

    @Autowired
    SftpStreamFactory sftpStreamFactory;

    SftpStream sftpStream = sftpStreamFactory.createStream(filePath);
    ObjectMetadata objectMetadata = new ObjectMetadata();
    objectMetadata.setContentLength(sftpStream.getSizeBytes());
    PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, sftpStream.getStream(), objectMetadata);
    putObjectRequest.setGeneralProgressListener(new UploadBeginEndNotificationListener(uploadRequest, statusNotifier));
    
    transferManager.upload(putObjectRequest);

这是SftpStream的定义:

@AllArgsConstructor
public class SftpStreamFactory {

@Getter
@AllArgsConstructor
public static class SftpStream {
    private final long sizeBytes;
    private final InputStream stream;
}

private final SftpRemoteFileTemplate sftpTemplate;
private final SftpProperties sftpProperties;

public SftpStream createStream(Path relativePath) {
    return sftpTemplate.<SftpStream, ChannelSftp>executeWithClient(session -> createStream(session, relativePath));
}

SftpStream createStream(ChannelSftp channelSftp, Path relativePath) {

    String path = sftpProperties.getRoot().resolve(relativePath).toString();

    try {
        SftpATTRS fileAttrs = channelSftp.lstat(path);
        long size = fileAttrs.getSize();
        return new SftpStream(size, channelSftp.get(path));
    }
    catch (SftpException e) {
        throw new UncheckedIOException(new NestedIOException("SFTP Error", e));
    }
}

}

这种上传方法效果很好。 但是,如果分段上传在中间暂停/取消/以其他方式中止,我们希望从中断的地方继续,而不是重新开始。 我们知道 TransferManagers resumeUpload方法采用PersistableUpload

但是,在PersistableUpload的 javadoc 中,它期望在构造函数中传递一个file路径,然后尝试从中创建一个File对象: https : //docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/ com/amazonaws/services/s3/transfer/PersistableUpload.html

我们想知道的是,有没有办法在没有这个文件对象的情况下恢复上传,而我们无法从ChannelSftp获得它? 也就是说,我们可以从流而不是文件恢复上传吗? 或者我们是否必须切换到使用低级别 s3 api 来执行这样的简历。 任何建议表示赞赏。

编辑 - 进一步研究,甚至为已经存在的上传传递一个 UploadId,如果没有文件,doUpload 方法将抛出异常。 有任何想法吗?

答案是,不,您不能在没有文件的情况下继续上传,但是对于您的类似情况,有一种解决方法:

#成功暂停前中止

  1. 当且仅当在任何中断发生之前尝试暂停连接
boolean forceCancel = true;
PauseResult<PersistableUpload> pauseResult = myUpload.tryPause(forceCancel);
  1. 保存info to resume数据info to resume到文件
PersistableUpload persistableUpload = pauseResult.getInfoToResume();

File f = new File("UNIQUE-ID-FOR-UPLOADED-FILE"); //blob
if (!f.exists())
    f.createNewFile();
FileOutputStream fos = new FileOutputStream(f);

// Serialize the persistable upload to the file.
persistableUpload.serialize(fos);
fos.close();
  1. 有时稍后继续
TransferManager tm = new TransferManager();
FileInputStream fis = new FileInputStream(new File("UNIQUE-ID-FOR-UPLOADED-FILE"));

// Deserialize PersistableUpload information from disk.
PersistableUpload persistableUpload = PersistableTransfer.deserializeFrom(fis);

// Call resumeUpload with PersistableUpload.
tm.resumeUpload(persistableUpload);

fis.close();

#SAVE 流以维护文件如果发生某些事情(例如 JVM 崩溃)

使用S3SyncProgressListenerTransferManager#upload来保存每个更改并将数据序列化到磁盘。

transferManager.upload(putObjectRequest, new S3SyncProgressListener() {

    ExecutorService executor = Executors.newFixedThreadPool(1);

    @Override
    public void onPersistableTransfer(final PersistableTransfer persistableTransfer) {

       executor.submit(new Runnable() {
          @Override
          public void run() {
              try {
                  File f = new File("UNIQUE-ID-FOR-UPLOADED-FILE");
                  if (!f.exists()) {
                      f.createNewFile();
                  }
                  FileOutputStream fos = new FileOutputStream(f);
                  persistableTransfer.serialize(fos);
                  fos.close();
              } catch (IOException e) {
                  throw new RuntimeException("Unable to persist transfer to disk.", e);
              }
          }
       });
    }
});

希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM