如何使用Camel aws-s3生产者将文件上传到AWS S3?

3

我正在尝试使用Camel的aws-s3生产者将jpg文件上传到AWS S3存储桶。我能否通过这种方式使其工作,如果可以,如何操作?现在我只得到了一个IOException,并且无法确定下一步该怎么做。我知道我可以使用aws-sdk中的TransferManager来实现上传,但现在我只对Camel的aws-s3端点感兴趣。

这是我的路由(使用Camel 2.15.3):

public void configure() {
    from("file://src/data?fileName=file.jpg&noop=true&delay=15m")
    .setHeader(S3Constants.KEY,constant("CamelFile"))
    .to("aws-s3://<bucket-name>?region=eu-west-1&accessKey=<key>&secretKey=RAW(<secret>)");
}

我运行该路由时得到的异常:

com.amazonaws.AmazonClientException: Unable to create HTTP entity: Stream Closed
at com.amazonaws.http.HttpRequestFactory.newBufferedHttpEntity(HttpRequestFactory.java:244)
at com.amazonaws.http.HttpRequestFactory.createHttpRequest(HttpRequestFactory.java:122)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:415)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:273)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3660)
at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:1432)
at org.apache.camel.component.aws.s3.S3Producer.processSingleOp(S3Producer.java:209)
at org.apache.camel.component.aws.s3.S3Producer.process(S3Producer.java:71)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:129)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:448)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:439)
at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:211)
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:175)
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:174)
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:101)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Stream Closed
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:246)
at com.amazonaws.services.s3.internal.RepeatableInputStream.read(RepeatableInputStream.java:167)
at com.amazonaws.internal.SdkFilterInputStream.read(SdkFilterInputStream.java:73)
at com.amazonaws.services.s3.internal.MD5DigestCalculatingInputStream.read(MD5DigestCalculatingInputStream.java:88)
at com.amazonaws.internal.SdkFilterInputStream.read(SdkFilterInputStream.java:73)
at com.amazonaws.event.ProgressInputStream.read(ProgressInputStream.java:151)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at org.apache.http.util.EntityUtils.toByteArray(EntityUtils.java:136)
at org.apache.http.entity.BufferedHttpEntity.<init>(BufferedHttpEntity.java:63)
at com.amazonaws.http.HttpRequestFactory.newBufferedHttpEntity(HttpRequestFactory.java:242)
... 27 more
2个回答

7
我做了一些调查,找到了一个解决方案。如果在将文件内容传递给aws-s3端点之前将其转换为字节数组,则路由会起作用,就像这样:
from("file://src/data?fileName=file.jpg&noop=true&delay=15m")
    .convertBodyTo(byte[].class)
    .setHeader(S3Constants.CONTENT_LENGTH, simple("${in.header.CamelFileLength}"))
    .setHeader(S3Constants.KEY,simple("${in.header.CamelFileNameOnly}"))
    .to("aws-s3://{{awsS3BucketName}}"
                    + "?deleteAfterWrite=false&region=eu-west-1"
                    + "&accessKey={{awsAccessKey}}"
                    + "&secretKey=RAW({{awsAccessKeySecret}})")
    .log("done.");
}

还必须设置S3Constants.CONTENT_LENGTH头文件的值为文件长度(以字节为单位)。

上述解决方案将整个文件读入内存,因此并不适用于每种情况。然而,上述代码也是我知道使用aws-s3生产者端点最简单的方式。我很乐意听取其他(更好的)解决方案。


如何在上传后从S3获取可下载的链接 - Bikesh M
1
Camel S3生产者不会在输出头中设置资源链接,但S3 URL的格式如下:https://s3-<REGION>.amazonaws.com/<BUCKET_NAME>/<OBJECT_KEY>,因此您可以根据区域、存储桶名称和对象键自行构建链接。 - jnupponen
@jnupponen - 你提到你正在使用Camel 2.15.3。你使用的Maven依赖是什么?我只能在Maven Central上看到Camel 3的依赖关系- https://mvnrepository.com/artifact/org.apache.camel/camel-aws-s3 - adesai
@adesai Camel 2.15.3 https://mvnrepository.com/artifact/org.apache.camel/camel-aws/2.15.3 然而,那是非常老的版本,我建议您使用最新的Camel依赖,就像您已经链接的那样。 - jnupponen

0

这里是使用camel xml dsl的示例。以下操作将根据文件src/empty.txt的内容,在S3存储桶中上传文件s3File.txt。我正在使用came 2.21.1。

<!--upload file to AWS S3 -->
<setHeader headerName="CamelAwsS3Key">
 <exchangeProperty>s3File.txt</exchangeProperty>
</setHeader>
<setBody>
   <!--fileName with location to be uploaded -->
  <exchangeProperty>src/localfile.txt</exchangeProperty>
</setBody>
<convertBodyTo type="java.io.File"/>

 <!--upload the file to s3 pvc medicare leg2 outbound bucket-->
 <to uri="aws-s3:bucketName?amazonS3Client=#s3Client"/>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接