java.lang.IollegalStateException:InputStream已被读取-如果一个流需要多次读取



我正试图从aws s3 bucket中读取一个文件,并将其设置为spring批处理读取器类中的资源。当我在aws lambda函数上测试应用程序时,我得到了以下错误。专家们有什么建议吗?

Caused by: java.lang.IllegalStateException: InputStream has already been read - do not use InputStreamResource if a stream needs to be read multiple times
at org.springframework.core.io.InputStreamResource.getInputStream(InputStreamResource.java:97) ~[task/:na]
at org.springframework.batch.item.file.DefaultBufferedReaderFactory.create(DefaultBufferedReaderFactory.java:34) ~[task/:na]
at org.springframework.batch.item.file.FlatFileItemReader.doOpen(FlatFileItemReader.java:266) ~[task/:na]
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:146) ~[task/:na]
Class to read from s3 bucket
@Service
public class S3BucketProcessing {
private static final AmazonS3 s3 = AmazonS3ClientBuilder.standard().build();
public InputStreamResource readFile() throws IOException{
String bucketName = "mybuckey";
String key = "File.txt";
S3Object object = s3.getObject(new GetObjectRequest(bucketName, key));    
return new InputStreamResource(object.getObjectContent());
}

春季批读取器类

@Component
public class MyReader extends FlatFileItemReader<MyEntity> {
MyLineMapper mapper;
MyTokenizer tokenizer;
S3BucketProcessing s3BucketProcessing;
@Autowired
public MyReader(MyTokenizer tokenizer, MyLineMapper mapper, S3BucketProcessing s3BucketProcessing) throws Exception{
LOG.info("CardCustomerNotificationReader constructor");
this.mapper = mapper;
this.tokenizer = tokenizer;
this.s3BucketProcessing= s3BucketProcessing;
this.setResource(s3BucketProcessing.readFile());
mapper.setLineTokenizer(tokenizer);
this.setLineMapper(mapper);
}
}

文档建议使用ByteArrayResource将内容缓存在内存中,而不是InputStreamResource。

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/InputStreamResource.html

只需更改退货部分如下:

//As suggested by berzerk
byte[] content = IOUtils.toByteArray(object.getObjectContent()); 
//Then
return new ByteArrayResource( content );

您不需要返回InputStreamResource,而是需要返回流的内容byte[]
byte[]content=IOUtils.toByteArray(object.getObjectContent(((;退货内容;

所以我不得不将JSON/XML对象作为输出流发送。我使用InputStreamResource,得到了与OP.相同的错误

这是对我有效的解决方案。

@Override
public Resource dataExportForFieldExtractorModel() {
ObjectMapper xmlMapper = new XmlMapper().enable(SerializationFeature.INDENT_OUTPUT);
byte[] data;
Resource resource = null;
try {
data = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsBytes(new DataExportResponse());
resource = new ByteArrayResource(data);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return resource;
}

由于资源需要为byte[],我将resource = new InputStreamResource(new ByteArrayInputStream(data));更改为resource = new ByteArrayResource(data);

最新更新