users@grizzly.java.net

Re: Upload a large file without oom with Grizzly

From: Sébastien Lorber <lorber.sebastien_at_gmail.com>
Date: Tue, 27 Aug 2013 13:08:27 +0200

Ok thanks!

I think I see what I could do, probably something like that:


    FeedableBodyGenerator bodyGenerator = new FeedableBodyGenerator();
    MultipartBodyGeneratorFeeder bodyGeneratorFeeder = new
MultipartBodyGeneratorFeeder(bodyGenerator);
    Request uploadRequest1 = new RequestBuilder("POST")
            .setUrl("url")
            .setBody(bodyGenerator)
            .build();

    ListenableFuture<Response> asyncRes = asyncHttpClient
        .prepareRequest(uploadRequest1)
        .execute(new AsyncCompletionHandlerBase());


    bodyGeneratorFeeder.append("param1","value1");
    bodyGeneratorFeeder.append("param2","value2");
    bodyGeneratorFeeder.append("fileToUpload",fileInputStream);
    bodyGeneratorFeeder.end();

    Response uploadResponse = asyncRes.get();


Does it seem ok to you?

I guess it could be interesting to provide that
MultipartBodyGeneratorFeeder class to AHC or Grizzly since some other
people may want to achieve the same thing





2013/8/26 Ryan Lubke <ryan.lubke_at_oracle.com>

>
>
> Sébastien Lorber wrote:
>
>> Hello,
>>
>> I would like to know if it's possible to upload a file with AHC / Grizzly
>> in streaming, I mean without loading the whole file bytes in memory.
>>
>> The default behavior seems to allocate a byte[] which contans the whole
>> file, so it means that my server can be OOM if too many users upload a
>> large file in the same time.
>>
>>
>> I've tryied with a Heap and ByteBuffer memory managers, with
>> reallocate=true/false but no more success.
>>
>> It seems the whole file content is appended wto the BufferOutputStream,
>> and then the underlying buffer is written.
>>
>> At least this seems to be the case with AHC integration:
>> https://github.com/**AsyncHttpClient/async-http-**client/blob/**
>> 6faf1f316e5546110b0779a5a42fd9**d03ba6bc15/providers/grizzly/**
>> src/main/java/org/**asynchttpclient/providers/**grizzly/bodyhandler/**
>> PartsBodyHandler.java<https://github.com/AsyncHttpClient/async-http-client/blob/6faf1f316e5546110b0779a5a42fd9d03ba6bc15/providers/grizzly/src/main/java/org/asynchttpclient/providers/grizzly/bodyhandler/PartsBodyHandler.java>
>>
>>
>> So, is there a way to patch AHC to stream the file so that I could
>> eventually consume only 20mo of heap while uploading a 500mo file?
>> Or is this simply impossible with Grizzly?
>> I didn't notice anything related to that in the documentation.
>>
> It's possible with the FeedableBodyGenerator. But if you're tied to using
> Multipart uploads, you'd have to convert the multipart data to Buffers
> manually and send using the FeedableBodyGenerator.
> I'll take a closer look to see if this area can be improved.
>
>
>> Btw in my case it is a file upload. I receive a file with CXF and have to
>> transmit it to a storage server (like S3). CXF doesn't consume memory
>> bevause it is streaming the large fle uploads to the file system, and then
>> provides an input stream on that file.
>>
>> Thanks
>>
>>
>>