Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get outputstream from an S3Object?

Tags:

My goal is to fetch an object (image) from S3, change the metadata of the file, and replace it with new file that has changed metadata.

For changing the metadata I am using commons imaging library. I have coded the sample below that works as expected but does not deal with S3.

File newFile = new File("newImage2.jpg");
OutputStream os = new BufferedOutputStream(new FileOutputStream(newFile))
InputStream isNew = new BufferedInputStream(new FileInputStream(newFile))
InputStream is = new BufferedInputStream(new FileInputStream(new File("newImage.jpg")))
try {
            String xmpXml = "<x:xmpmeta>" +
            "\n<Lifeshare>" +
            "\n\t<Date>"+"some date"+"</Date>" +
            "\n\t<Latitude>"+"somelat"+"</Latitude>" +
            "\n\t<Longitude>"+"somelong"+"</Longitude>" +
            "\n\t<Altitude>"+"somealt"+"</Altitude>" +
            "\n\t<Z>"+"someZ"+"</Z>" +
            "\n\t<X>"+"someX"+"</X>" +
            "\n\t<Y>"+"Some y"+"</Y>" +
            "\n</Lifeshare>" +
            "\n</x:xmpmeta>";
            JpegXmpRewriter rewriter = new JpegXmpRewriter();
            rewriter.updateXmpXml(is,os, xmpXml);
            String newXmpXml = Imaging.getXmpXml(isNew, "newImage2.jpg");
            println newXmpXml
        }
finally {
   is.close()
   os.close()
}

The above works since I can run exiftool on the newimage2.jpg and view the set metadata properties:

$ exiftool newImage2.jpg | grep "Lifeshare"
Lifeshare Date                  : some date
Lifeshare Latitude              : somelat
Lifeshare Longitude             : somelong
Lifeshare Altitude              : somealt
Lifeshare Z                     : someZ
Lifeshare X                     : someX
Lifeshare Y                     : Some y

Question

How can I do the same using an object on S3 using AWS S3 SDK? The updateXmpXml method above requires OutputStream as a second parameter. However, I don't see any outputstream class in the AWS sdk http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/allclasses-noframe.html

like image 406
Anthony Avatar asked Oct 26 '16 12:10

Anthony


People also ask

How do I get content from S3Object?

You can get the object's contents by calling getObjectContent on the S3Object . This returns an S3ObjectInputStream that behaves as a standard Java InputStream object.

Do you need to close S3Object?

If you retrieve an S3Object, you should close this input stream as soon as possible, because the object contents aren't buffered in memory and stream directly from Amazon S3. Further, failure to close this stream can cause the request pool to become blocked.


1 Answers

http://docs.aws.amazon.com/AmazonS3/latest/dev/RetrievingObjectUsingJava.html

using apache ioutils

OutputStream os = new ByteArrayOutputStream();


    AmazonS3 s3Client = new AmazonS3Client(new ProfileCredentialsProvider());        
    S3Object object = s3Client.getObject(
                      new GetObjectRequest(bucketName, key));
    InputStream in= object.getObjectContent();
    IOUtils.copy(in, out);

    in.close();
    out.close();
like image 64
kuhajeyan Avatar answered Sep 25 '22 16:09

kuhajeyan