我的目标是:
AWS java SDK不允许推送输出流。因此,我必须将outputstream
从第2步转换为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的所有内容?
答案 0 :(得分:1)
当你执行os.writeTo(out)时,它会尝试将整个流刷新到 out ,并且由于没有人从它的另一端读取(即inpipe),内部缓冲区填满,线程停止。
您必须在编写数据之前设置阅读器,并确保它在单独的线程中执行(请参阅PipedOutputStream上的javadoc)。
答案 1 :(得分:0)
根据Bharal的要求,由于上述评论,我本人亲自解决了此问题。因此,添加该示例代码。希望它能帮助别人!
public void doSomething() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("some bytes to stick in the stream".getBytes());
InputStream inStr = toInputStream(baos);
}
public InputStream toInputStream(ByteArrayOutputStream orgOutStream) throws IOException{
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
try{
new Thread(((Runnable)() -> {
try{
orgOutStream.writeTo(out);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
})).start();
} finally{
orgOutStream.close();
}
return in;
}
真正的诀窍是确保通过管道调用在单独的线程中完成。