JavaFX – Upload and Download Large Files


We can upload or download large files using new HttpRequest attributes available in JavaFX 1.2.

HttpRequest has input and onInput attributes that provides InputStream which can be used to download data. This stream supports mark, reset, available, skip etc. But to support this HttpRequest buffers the data. Due to this buffering it was not possible to use this approach to download large files.

JavaFX 1.2 introduce two new attributes – source (InputStream) and sink (OutputStream). If we set sink attribute, we can directly download the content of stream without buffering. Also with source we can upload the content. Eg: By setting it to FileInputStream. When source or sink attribute is used, corresponding input, onInput, output, onOutput will not be functional.

For Applet mode, click on above image

For standalone mode

The application downloads a larger version of the photo. I took it from Somnathpur using Nikon Coolpix! 🙂


function downloadFile(url , outputFile) {

    def getRequest: HttpRequest = HttpRequest {

        location: url
        sink: new java.io.FileOutputStream(outputFile)

        onToRead: function(bytes: Long) {
            toRead = bytes;
            println("onToRead({bytes})");
        }

        onRead: function(bytes: Long) {
            read = bytes;
            println("onRead - {read * 100/toRead}%");
        }

        onDone: function() { println("onDone") }
    }

    getRequest.start();
}

In above sample, sink is assigned to a FileOutputStream. So all the content will be directly written to file without buffering. Note: For making the application compatible with mobile or other platforms we will have to use only subset of java.io package. Example: MID Profile Core API.

Source:

Advertisements

About Rakesh Menon
-

19 Responses to JavaFX – Upload and Download Large Files

  1. Arno Raps says:

    For some reason, I can’t get the upload progress. Download progress values (like read etc.) are ok, but not when uploading.
    I can see the uploading is working (and the onDone method is called) is this a bug?

  2. Rakesh Menon says:

    @Arno Raps For POST request, you can listen to onWritten which provides the total bytes written to stream. onToWrite will return -1, the application needs to compute the total bytes that will be written.

  3. Arno Raps says:

    Thanks for answering, but the problem is when I use the source method:
    source: new java.io.FileInputStream("d://somebigfile");
    I get a:
    onConnecting
    onDoneConnect
    onWritten: 65536
    onWritten: 131072
    onWritten: 196608

    onWritten: 2236696
    onReadingHeaders
    ****************************************
    Progress: 2236696
    written: 2236696
    So it looks like the source stream is buffered anyway (I can see in my netwerk that the upload is busy for a while after this)

  4. Rakesh Menon says:

    @Arno Raps It does create a byte array of 64kb, but will not buffer the entire content before upload or download. For desktop implementation in this case it creates a URLConnection and writes directly to its OutputStream

  5. Arno Raps says:

    But how can I monitor its progress than? the onWritten isn’t the correct value of the real bytes send thru the network. I would like to have such a progress to report to the client, just like the progress bar in your download example.

  6. Rakesh Menon says:

    @Arno Raps onWritten does provide the correct value every 64kb, which is fine for large files. For small files instead of specifying "source", obtain the OutputStream from onOutput. Also if you use "source" then there is no way to find the size of total bytes of data that will be written (as there is no buffering). In case of read, the total bytes to be read is obtained from Content-Length HTTP header.

  7. Arno Raps says:

    In my code, the onWritten events are long done when the upload is working:
    onConnecting
    onDoneConnect
    onWritten: 65536
    onWritten: 131072
    onWritten: 196608

    onWritten: 2236696
    onReadingHeaders
    (this was a 2.2 MB file upload. These lines (in 64K increments al happend in 1 second, while de file upload takes several minutes ( a 448 kbps upstream here )

  8. Rakesh Menon says:

    @Arno Raps I discussed issue with developer. Please file a bug with this testcase, so that he can investigate further. It may be due to delayed response from server. But need to do some further investigation.
    http://javafx-jira.kenai.com/secure/Dashboard.jspa

  9. Arno Raps says:

    I’ve made a bug issue:
    You have successfully created the issue (RT-5027), however you do not have the permission to view the created issue.

  10. Rakesh Menon says:

    @Arno Raps Thanks a lot.. I have updated bug to make it public. Hope now you can view the issue. It will be reviewed by the developer.

  11. Gabriel says:

    Hi Rakesh,
    Currently I have been working with the HttpRequest trying to upload large files but I have had some problems to upload the file because the file is not received by my servlet. I dont know if I am missing something in the HttRequest declaration, below my HttpRequest code:
    uploadRequest = HttpRequest{
    location: url
    headers : [HttpHeader {
    name:HttpHeader.ACCEPT
    value: "*/*"},
    HttpHeader {
    name:HttpHeader.CONTENT_TYPE
    value: "multipart/form-data;"},
    HttpHeader {
    name:HttpHeader.CONNECTION
    value: "keep-alive"},
    HttpHeader {
    name:HttpHeader.CACHE_CONTROL
    value: "{"no-cache"}"
    },
    HttpHeader {
    name:HttpHeader.ACCEPT_CHARSET
    value: "{"ISO-8859-1,utf-8;q=0.7,*;q=0.7"}"
    },
    HttpHeader{
    name: "Content-Disposition:"
    value: "form-data; name="upfile";},
    HttpHeader
    {name: "Content-Type:"
    value: "application/octet-stream"}]
    source: new java.io.FileInputStream(file)
    method: HttpRequest.POST
    onStarted:function():Void{println("started");}
    onWritten:function(size: Long):Void {println("onWritten – {size} bytes has now been written");}
    onException: function (ex:java.lang.Exception):Void { println("onException – exception: {ex.getClass()} {ex.getMessage()}");}
    onDone: function():Void { println("onDone");stop();}
    onToWrite: function(bytes:Long){println("onToWrite");}
    onWriting: function(){println("onWriting");}
    onRead: function(bytes: Long):Void {
    println("onRead – bytes read: {bytes}");
    }
    onInput: function(is: java.io.InputStream):Void {println("onInput");
    try { println("onInput – bytes of content available: {is.available()}"); } finally { is.close();}
    }
    onOutput: function(os:OutputStream):Void{
    println("onOutput");}
    };
    uploadRequest.start();
    Thanks in advance.

  12. Rakesh Menon says:

    @Gabriel Can you provide a bit more info? When you say "file is not received by my servlet", is the request received by servlet? Does it work fine if you use onInput (for small files)?

  13. Mark says:

    Hi Rakesh
    I am working on how to upload files with the HttpRequest in javafx.I just began to learn javafx a couple of weeks ago.I want to use it to upload files in my programe,but I have a big problem.Can you give me a example of uploading images from a client to a server?
    thanks in advance

  14. Ted says:

    Hi Rakesh
    I got an other question now.
    I want to use the javafx programe in the browser,but there are a few questions.I can’t open local resourses in this programe.I guess there is something related to permission,can you give me a way to solve it?

  15. Rakesh Menon says:

    @Mark This depends on how the server is implemented. I can provide another sample including a simple server side jsp/servlet.

  16. Rakesh Menon says:

    @Ted For accessing local resources the application needs to be signed.
    Assuming you are using NetBeans, you can goto Project-Properties -> Application -> Check "Self Signed Jar". Then rebuild the application.

  17. Pingback: JavaFX – Upload File « Rakesh Menon

  18. Ginkan says:

    could you please write a tutorial for “HttpRequest / sink” in mobile??
    the following code is a part of a simple downloading app in mobile, it took my couple of month and still cannot solve the “sink” problem:

    def HttpRequest$1: HttpRequest = HttpRequest {
    def fc$1:FileConnection = Connector.open(“file:///xxx.jpg”) as FileConnection;
    location:”http://www.xxx.com/xxx.jpg”
    sink: fc$1.openOutputStream() //<——- HELP =]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: