Spring Boot java.lang.IllegalStateException:InputStream已经被读取-如果需要多次读取流,请不要使用InputStreamResource

yqyhoc1h  于 2023-11-17  发布在  Spring
关注(0)|答案(3)|浏览(333)

我试图从aws s3 bucket中读取文件,并将其设置为spring batch reader类中的资源。当我在aws lambda函数上测试应用程序时,我得到了以下错误。Maven有什么建议吗?

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

字符串
Spring批处理读取器类

  1. @Component
  2. public class MyReader extends FlatFileItemReader<MyEntity> {
  3. MyLineMapper mapper;
  4. MyTokenizer tokenizer;
  5. S3BucketProcessing s3BucketProcessing;
  6. @Autowired
  7. public MyReader(MyTokenizer tokenizer, MyLineMapper mapper, S3BucketProcessing s3BucketProcessing) throws Exception{
  8. LOG.info("CardCustomerNotificationReader constructor");
  9. this.mapper = mapper;
  10. this.tokenizer = tokenizer;
  11. this.s3BucketProcessing= s3BucketProcessing;
  12. this.setResource(s3BucketProcessing.readFile());
  13. mapper.setLineTokenizer(tokenizer);
  14. this.setLineMapper(mapper);
  15. }
  16. }

yc0p9oo0

yc0p9oo01#

文档建议使用ByteArrayResource将内容缓存在内存中,而不是InputStreamResource。
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/InputStreamResource.html
只需像这样更改返回部分:

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

字符串

bgibtngc

bgibtngc2#

而不是返回InputStreamResource,你shud返回流的内容可能是byte[]

  1. byte[] content = IOUtils.toByteArray(object.getObjectContent());
  2. return content ;

字符串

zpgglvta

zpgglvta3#

所以我必须将JSON/XML对象作为输出流发送。我使用的是InputStreamResource,得到的错误与OP相同。
这是对我有效的解决方案。

  1. @Override
  2. public Resource dataExportForFieldExtractorModel() {
  3. ObjectMapper xmlMapper = new XmlMapper().enable(SerializationFeature.INDENT_OUTPUT);
  4. byte[] data;
  5. Resource resource = null;
  6. try {
  7. data = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsBytes(new DataExportResponse());
  8. resource = new ByteArrayResource(data);
  9. } catch (JsonProcessingException e) {
  10. e.printStackTrace();
  11. }
  12. return resource;
  13. }

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

展开查看全部

相关问题