我的目标是:

  • 从S3读取文件
  • 更改其元数据
  • 再次将其推入S3

  • AWS Java SDK不允许推送输出流。因此,我必须将step2的outputstream转换为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字节。文件不完整。我如何编写从outputstream到S3的所有内容?

    最佳答案

    当您执行os.writeTo(out)时,它将尝试刷新整个流以将其输出,并且由于还没有人从另一侧读取内容(即inpipe),因此内部缓冲区已满并且线程停止了。

    在写入数据之前,必须先设置阅读器,并确保它在单独的线程中执行(请参阅PipedOutputStream上的javadoc)。

    09-11 20:05