3

私の目標は次のとおりです。

  1. S3からファイルを読み取り、
  2. メタデータの変更
  3. 再度 S3 にプッシュする

AWS Java SDK では、出力ストリームをプッシュできません。したがって、 をoutputstreamstep2 からに変換する必要がありinputstreamます。このために、 を使用することにしましPipedInputStreamた。

ただし、私のコードはステップでハングしますwriteTo(out);。このコードは grails アプリケーションにあります。コードがハングするとき、CPU の消費は高くありません。

import org.apache.commons.imaging.formats.jpeg.xmp.JpegXmpRewriter;

AmazonS3Client client = nfile.getS3Client() //get S3 client
S3Object object1 = client.getObject(
                  new GetObjectRequest("test-bucket", "myfile.jpg")) //get the object. 

InputStream isNew1 = object1.getObjectContent(); //create input stream
ByteArrayOutputStream os = new ByteArrayOutputStream();
PipedInputStream inpipe = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(inpipe);

try {
   String xmpXml = "<x:xmpmeta>" +
    "\n<Lifeshare>" +
    "\n\t<Date>"+"some date"+"</Date>" +
    "\n</Lifeshare>" +
    "\n</x:xmpmeta>";/
   JpegXmpRewriter rewriter = new JpegXmpRewriter();
   rewriter.updateXmpXml(isNew1,os, xmpXml); //This is step2

   try {
new Thread(new Runnable() {
    public void run () {
        try {
            // write the original OutputStream to the PipedOutputStream
            println "starting writeto"
            os.writeTo(out);
            println "ending writeto"
        } catch (IOException e) {
            // logging and exception handling should go here
        }
    }
}).start();

         ObjectMetadata metadata = new ObjectMetadata();
         metadata.setContentLength(1024); //just testing
         client.putObject(new PutObjectRequest("test-bucket", "myfile_copy.jpg", inpipe, metadata));
         os.writeTo(out);

         os.close();
         out.close();
   } catch (IOException e) {
         // logging and exception handling should go here
   }

}
finally {
   isNew1.close()
   os.close()
   out.close()
}

上記のコードは、印刷starting writetoされてハングします。印刷されませんending writeto

更新を別のスレッドに 入れることwriteToで、ファイルは S3 に書き込まれるようになりましたが、書き込まれるのは 1024 バイトだけです。ファイルが不完全です。出力ストリームから S3 にすべてを書き込むにはどうすればよいですか?

4

2 に答える 2

2

os.writeTo(out) を実行すると、ストリーム全体をoutにフラッシュしようとしますが、その反対側 (つまり inpipe) からまだ誰も読み取っていないため、内部バッファーがいっぱいになり、スレッドが停止します。

データを書き込む前にリーダーをセットアップする必要があります。また、リーダーが別のスレッドで実行されるようにする必要があります (PipedOutputStream の javadoc を参照)。

于 2016-10-26T19:49:22.050 に答える