RFR: 8329829: HttpClient: Add a BodyPublishers.ofFileChannel method
Daniel Fuchs
dfuchs at openjdk.org
Mon Jul 7 08:47:40 UTC 2025
On Mon, 7 Jul 2025 07:33:58 GMT, Volkan Yazici <vyazici at openjdk.org> wrote:
> Adds a new `ofFileChannel(FileChannel channel, long offset, long length)` method to `java.net.HttpRequest.BodyPublishers` to provide an `HttpClient` publisher to upload a certain region of a file. The new publisher does not modify the state of the passed `FileChannel`, streams the file channel bytes as it publishes (i.e., avoids reading the entire file into the memory), and can be leveraged to implement sliced uploads. As noted in the Javadoc:
>
>> The file channel will not be closed upon completion. The caller is
>> expected to manage the life cycle of the channel, and close it
>> appropriately when not needed anymore.
>
> ### Implementation notes
>
> - `FileChannel` is preferred over `{Readable,Seekable}ByteChannel`, since the latter does not provide a positional read without modifying the state of the `FileChannel`, which is necessary to use a single `FileChannel` instance to implement sliced uploads.
> - `ofFileChannel(FileChannel,long,long)` is preferred over `ofPath(Path,long,long)` to avoid overloading the maximum file descriptor limit of the platform.
src/java.net.http/share/classes/java/net/http/HttpRequest.java line 739:
> 737: * @param channel a file channel
> 738: * @param offset the offset of the first byte
> 739: * @param length the number of bytes to use
I'd suggest to say something like:
> the number of bytes to send
or
> the number of bytes to read from the file channel
src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java line 488:
> 486: ByteBuffer buffer = Utils.BUFSIZE > remaining
> 487: ? Utils.getBufferWithAtMost((int) remaining)
> 488: : Utils.getBuffer();
I suggest to change `Utils.getBufferWithAtMost` to take a long instead of an int, and replace the ternary operator here with simply:
ByteBuffer buffer = Utils.getBufferWithAtMost(remaining);
src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java line 386:
> 384: * @throws IllegalArgumentException if {@code capacity < 0}
> 385: */
> 386: public static ByteBuffer getBufferWithAtMost(int maxCapacity) {
Suggestion:
public static ByteBuffer getBufferWithAtMost(long maxCapacity) {
We could accept `long` here.
src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java line 392:
> 390: "capacity < 0: (%s < 0)".formatted(maxCapacity));
> 391: }
> 392: int effectiveCapacity = Math.clamp(maxCapacity, 0, BUFSIZE);
Suggestion:
int effectiveCapacity = (int) Math.min(maxCapacity, (long) BUFSIZE);
Use Math.min(long,long) - since BUFZIZE is an int we can safely cast back to int. No need to clamp at 0 since we verified maxCapacity >= 0
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/26155#discussion_r2189357089
PR Review Comment: https://git.openjdk.org/jdk/pull/26155#discussion_r2189371496
PR Review Comment: https://git.openjdk.org/jdk/pull/26155#discussion_r2189386033
PR Review Comment: https://git.openjdk.org/jdk/pull/26155#discussion_r2189383920
More information about the net-dev
mailing list