【问题标题】:Spring RestController receive a huge size byteArray As RequestBody leads to not enough memory errorSpring RestController 收到一个巨大的 byteArray As RequestBody 导致内存不足错误
【发布时间】:2018-01-22 15:55:01
【问题描述】:

我有接受 byte[] 作为 RequestBody 的 RestApi 端点。但是,它使用了太多的内存。如何读取这个大字节 [] 数组?

有没有更好的方法来做到这一点?

我当前不起作用的解决方案如下:

控制器:

@RequestMapping(value = "person", method = RequestMethod.POST)public 
void postPerson(@RequestBody() byte[] data) {
  PersonService.postPerson(data);
}

服务:

public void postPerson(byte[] data) {

Splitter sp = new Splitter();

    sp.splitFile(data, (bytes) -> {

    });
}

界面:

public interface Splitter {
    void splitFile(byte[] data, Consumer<byte[]> segmentConsumer);
}

分离器:

public void splitFile(byte[] data, Consumer<byte[]> segmentConsumer){

    try {
        XMLInputFactory xmlif = XMLInputFactory.newInstance();
        final XMLEventReader reader = xmlif.createXMLEventReader(new 
        ByteArrayInputStream(data), StandardCharsets.ISO_8859_1.name());

        String fileHeader = "";

        StringBuilder aggregatedSegments = new StringBuilder();
        int segmentCount = 0;

        while (reader.hasNext()) {
            final XMLEvent event = reader.nextEvent();

            if (isStartElement(event, "status")) {
                fileHeader = buildHeader(event, reader);
            }

            if (isStartElement(event, "person")) {
                segmentCount++;
                aggregatedSegments.append(buildSegment(event, reader));
                if (maxNrOfElementsInSegment == segmentCount) {
                    segmentConsumer.accept(buildFile(fileHeader, aggregatedSegments));
                    aggregatedSegments = new StringBuilder();
                    segmentCount = 0;
                }
            }
        }
        if (segmentCount != 0) {
            segmentConsumer.accept(buildFile(fileHeader, aggregatedSegments));
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }    
}

【问题讨论】:

  • 请为我们提供一个代码sn-p。
  • 控制器中的大字节数组让我不得不增加堆。但这不是长期解决方案。
  • 作为 FYI,使用 \@Service 注释的对象用于注释绑定到域模型的弹簧组件。我不知道这是不是你的。我可能会用 \@Component 来注释它。它不能解决您的问题,但我认为您应该知道。 [Spring java 文档中的服务注解] (docs.spring.io/spring/docs/current/javadoc-api/org/…)
  • 你能提供你看到的异常/堆栈跟踪或错误吗?
  • 看来这是一个不错的解决方案。 boplicity.nl/knowledgebase/spring/…

标签: java arrays spring memory-leaks inputstream


【解决方案1】:
@RequestMapping(value = "", method = RequestMethod.POST)
public void postTransportEvent(HttpServletRequest request) {
File streamedFile = new File("test.xml");

    try {
        InputStream inputStream = request.getInputStream();

        if (inputStream != null) {
            FileOutputStream outputStream = new FileOutputStream(streamedFile);

            byte[] buffer = new byte[10240];
            int bytesRead;

            while ((bytesRead = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.flush();
            outputStream.close();
        }

        inputFileStream.close();

    } catch (IOException e) {
        log.error(e.toString(), e);
    } finally {
        streamedFile.delete();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多