Repository: quarkusio/quarkus
Issue: Cannot download a large file using RESTEasy Reactive

### Describe the bug

I recently switched to resteasy-reactive for my application, and I'm now unable to download large files.
If I try to create a response with the following syntax:

```java
response = Response.ok(file);
```

It fails for files larger than 2GB because it tries to buffer them but it is not possible to instantiate a ByteArrayOutputStream larger than MAX_INT (there is basically an integer overflow when calling the constructor and I end up with `Request failed: java.lang.IllegalArgumentException: Negative initial size`).

When I try to pass a FileInputStream as the response entity, it does work but my application maxes one of my CPU core during the download, and if the download gets interrupted the inputstream is never closed.

### Expected behavior

It should be possible to send large files as response entities using resteasy-reactive without maxing CPU usage.

### Actual behavior

Using a File type leads to integer overflow when instantiating the response outputstream, using an inputstream maxes a CPU core and never closes the file descriptor if interrupted.

### How to Reproduce?

1. Use resteasy-reactive
2. Build a service that sends a file
3. Request a file larger than Integer.MAX_INT bytes

### Output of `uname -a` or `ver`

Linux 5.13.13-arch1-1 #1 SMP PREEMPT Thu, 26 Aug 2021 19:14:36 +0000 x86_64 GNU/Linux

### Output of `java -version`

openjdk 11.0.12 2021-07-20

### GraalVM version (if different from Java)

GraalVM 21.3.0 Java 11 CE (Java Version 11.0.13+7-jvmci-21.3-b05)

### Quarkus version or git rev

2.5.1.Final

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)

### Additional information

_No response_

Changed files:
independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java
independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerFileBodyHandler.java

diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java
index 88d6c1b4bb1..aba7b355d23 100644
--- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java
+++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/InputStreamMessageBodyHandler.java
@@ -30,9 +30,10 @@ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotat
     public void writeTo(InputStream inputStream, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
             MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
         try {
+            byte[] buffer = new byte[8192];
             int c;
-            while ((c = inputStream.read()) != -1) {
-                entityStream.write(c);
+            while ((c = inputStream.read(buffer)) != -1) {
+                entityStream.write(buffer, 0, c);
             }
         } finally {
             try {
@@ -40,6 +41,11 @@ public void writeTo(InputStream inputStream, Class<?> type, Type genericType, An
             } catch (IOException e) {
                 // Drop the exception so we don't mask real IO errors
             }
+            try {
+                entityStream.close();
+            } catch (IOException e) {
+                // Drop the exception so we don't mask real IO errors
+            }
         }
     }
 }
diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerFileBodyHandler.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerFileBodyHandler.java
index 29ee04f42fd..4cc98c58c3c 100644
--- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerFileBodyHandler.java
+++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/providers/serialisers/ServerFileBodyHandler.java
@@ -1,8 +1,6 @@
 package org.jboss.resteasy.reactive.server.providers.serialisers;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import javax.ws.rs.Consumes;
@@ -12,12 +10,9 @@
 import javax.ws.rs.ext.Provider;
 import org.jboss.resteasy.reactive.common.providers.serialisers.FileBodyHandler;
 import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveResourceInfo;
-import org.jboss.resteasy.reactive.server.spi.ServerHttpResponse;
 import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter;
 import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;
 
-// TODO: this is very simplistic at the moment
-
 @Provider
 @Produces("*/*")
 @Consumes("*/*")
@@ -35,13 +30,6 @@ public boolean isWriteable(Class<?> type, Type genericType, ResteasyReactiveReso
 
     @Override
     public void writeResponse(File o, Type genericType, ServerRequestContext context) throws WebApplicationException {
-        ServerHttpResponse vertxResponse = context.serverResponse();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream((int) o.length());
-        try {
-            doWrite(o, baos);
-        } catch (IOException e) {
-            throw new WebApplicationException(e);
-        }
-        vertxResponse.end(baos.toByteArray());
+        context.serverResponse().sendFile(o.getAbsolutePath(), 0, o.length());
     }
 }