如何将输入流从ftp服务器直接传输到S3分段上传?

时间:2015-01-16 11:44:07

标签: java file-upload amazon-s3 sftp jsch

我正在尝试将一个大文件(aprrox 2gb到3gb)从客户端的FTP服务器上传到我的Amazon S3存储桶位置。
现在我不允许将整个文件存储在我的远程应用程序服务器中,所以不允许中间停止。除了SFTP之外,我对客户端ftp服务器没有其他访问权限 你有什么特别的建议吗?
此外,我现在使用JSCH库将Ftp服务器中的文件作为Inputstream读取,然后将相同的Inputstream传递给UploadPartRequest。另请注意,我能够使用JSCH库从客户端接收文件大小,以便生成多部分文件。 这是我一直在尝试的示例代码。

BasicAWSCredentials awsCreds = new BasicAWSCredentials(awsKey, awsSecretKey);
    AmazonS3 s3Client = new AmazonS3Client(awsCreds);
    List<PartETag> partETags = new ArrayList<PartETag>();
    InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(existingBucketName, keyName);
    InitiateMultipartUploadResult initResponse = s3Client.initiateMultipartUpload(initRequest);
    try {
        long partSize = 50 * 1024 * 1024;
        jsch= new JSch();
        session = jsch.getSession(ftpUserName, ftpLocation, 22);
        session.setPassword(password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.setTimeout(0);
        session.connect();
        System.out.println("session connected ......" + session.isConnected());
        channel = session.openChannel("sftp");
        channel.connect();
        System.out.println("channel connected...." + channel.isConnected());
        c = (ChannelSftp) channel;
        SftpATTRS attrs = c.lstat(filePath);
        long contentLength = attrs.getSize();
        InputStream is = c.get(filePath);
        System.out.println("size of the file in remote location is : " + contentLength/(1024*1024) +" MB" );
        long filePosition = 0;
        for (int i = 1; filePosition < contentLength; i++) {
            partSize = Math.min(partSize, (contentLength - filePosition));
            UploadPartRequest uploadRequest = new UploadPartRequest().withBucketName(existingBucketName)
                    .withKey(keyName).withUploadId(initResponse.getUploadId())
                    .withPartNumber(i).withFileOffset(filePosition).withInputStream(is).withPartSize(partSize);
            boolean anotherPass;
            do {
                anotherPass = false;
                try {
                    partETags.add(s3Client.uploadPart(uploadRequest).getPartETag());
                } catch (Exception e) {
                    anotherPass = true;
                }
            } while (anotherPass);

        filePosition += partSize;
            System.out.println("new file pos is : " + filePosition/(1024*1024) +" MB");
        }
        CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(existingBucketName, keyName, initResponse.getUploadId(), partETags);
        s3Client.completeMultipartUpload(compRequest);
    } catch (Exception ex){
        System.out.println("Exception occurred : " + ex.getMessage());
        s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(
                existingBucketName, keyName, initResponse.getUploadId()));
        ex.printStackTrace();
    }finally {
        System.out.println("closing all connections !!!!");
        if(session != null){
            session.disconnect();
        }if(channel != null){
            channel.disconnect();
        }if(c != null){
            c.disconnect();
        }
    }


现在有了这种方法,当上传到达中间的某个地方时,整个上传过程就会停止。应用程序正在运行,但没有上传或下载网络,上传停止在50%左右。
有任何建议吗???

1 个答案:

答案 0 :(得分:0)

要调试这个,我会试着看看问题出在哪里。

首先,您可以将此代码解耦以从FTP连接中获取小型的字节数组缓冲区(如10k),并在每次迭代时抛出缓冲区(不要将其发送到S3),以查看是否仍然挂起或不挂。

如果这样可行,你可以一次一个地将这个字节块发送给S3,看看会发生什么。