fix: use FileChannel.transferTo for zero-copy file serving
Build & Deploy / build-and-deploy (push) Failing after 27s
Build & Deploy / build-and-deploy (push) Failing after 27s
Replaced RandomAccessFile + manual 8KB buffer loop with FileChannel.transferTo() which uses OS sendfile — zero copy from disk cache to network socket. Eliminates Java heap churn and matches the old Files.copy() performance while supporting offset/length for HTTP Range requests.
This commit is contained in:
@@ -161,24 +161,15 @@ public class StaticResource {
|
||||
|
||||
/**
|
||||
* Streaming file output that avoids loading the whole file into memory.
|
||||
* Supports partial reads (seek + limit) for HTTP Range requests.
|
||||
* Supports partial reads (offset + length) for HTTP Range requests.
|
||||
* Uses FileChannel.transferTo() for zero-copy sendfile semantics.
|
||||
*/
|
||||
private record FileStream(Path file, long offset, long length) implements StreamingOutput {
|
||||
@Override
|
||||
public void write(OutputStream output) throws IOException {
|
||||
try (var raf = new RandomAccessFile(file.toFile(), "r");
|
||||
var channel = raf.getChannel()) {
|
||||
if (offset > 0) {
|
||||
raf.seek(offset);
|
||||
}
|
||||
long remaining = length;
|
||||
byte[] buf = new byte[8192];
|
||||
while (remaining > 0) {
|
||||
int toRead = (int) Math.min(buf.length, remaining);
|
||||
int read = raf.read(buf, 0, toRead);
|
||||
if (read < 0) break;
|
||||
output.write(buf, 0, read);
|
||||
remaining -= read;
|
||||
try (FileChannel ch = FileChannel.open(file, StandardOpenOption.READ)) {
|
||||
if (length > 0) {
|
||||
ch.transferTo(offset, length, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user