Spring RestController收到一个巨大的byteArray As RequestBody导致内存不足错误
Spring RestController receive a huge size byteArray As RequestBody leads to not enough memory error
我的 RestApi 端点接受 byte[] 作为 RequestBody。但是,它使用太多内存。我怎样才能读取这个大 byte[] 数组?
有没有更好的方法来做到这一点?
我当前无效的解决方案如下:
控制器:
@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);
}
}
@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();
}
我的 RestApi 端点接受 byte[] 作为 RequestBody。但是,它使用太多内存。我怎样才能读取这个大 byte[] 数组?
有没有更好的方法来做到这一点?
我当前无效的解决方案如下:
控制器:
@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);
}
}
@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();
}