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.

<script src="http://dl.javafx.com/1.2/dtfx.js"></script><script src="/rakeshmenonp/resource/UploadDownload/UploadDownload.js"></script>

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:

Update: Please refer to post on Upload File as well.

<script type="text/javascript">var dzone_url = "http://blogs.sun.com/rakeshmenonp/entry/javafx_upload_and_download_large";</script> <script type="text/javascript">var dzone_style = '2';</script> <script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script>

Comments:

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?

Posted by Arno Raps on June 24, 2009 at 10:24 AM IST #

@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.

Posted by Rakesh Menon on June 25, 2009 at 04:45 AM IST #

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)

Posted by Arno Raps on June 25, 2009 at 07:51 AM IST #

@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

Posted by Rakesh Menon on June 25, 2009 at 08:25 AM IST #

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.

Posted by Arno Raps on June 25, 2009 at 08:39 AM IST #

@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.

Posted by Rakesh Menon on June 25, 2009 at 10:15 AM IST #

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 )

Posted by Arno Raps on June 25, 2009 at 11:57 AM IST #

@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

Posted by Rakesh Menon on June 26, 2009 at 03:44 AM IST #

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.

Posted by Arno Raps on June 26, 2009 at 06:45 AM IST #

@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.

Posted by Rakesh Menon on June 26, 2009 at 07:37 AM IST #

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.

Posted by Gabriel on December 03, 2009 at 04:58 PM IST #

@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)?

Posted by Rakesh Menon on December 15, 2009 at 05:24 AM IST #

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

Posted by Mark on December 25, 2009 at 11:25 AM IST #

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?

Posted by Ted on December 27, 2009 at 12:26 AM IST #

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

Posted by Rakesh Menon on December 30, 2009 at 01:13 AM IST #

@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.

Posted by Rakesh Menon on December 30, 2009 at 01:16 AM IST #

Hi Rakesh.
I have some problem about how to upload file to server.
If client side is jsp, just create <input name="file" type="file" id="file"> then it can submit and send file to servlet to handle the file uploading (I use Apache Commons FileUpload)
then I try to send request from javafx to servlet.
Javafx can send request to get some string from servlet but I have no idea how to send file from javafx to servlet.
I found example code on http://sites.google.com/site/javafxcodesamples/experiments-1/http-file-upload-with-javafx but it's does't work.
Can you give me a example or idea how to upload file from a client to a server?
so

Posted by interviewz on January 31, 2010 at 12:05 PM IST #

@interviewz I have a new post on file upload

http://blogs.sun.com/rakeshmenonp/entry/javafx_upload_file

Posted by Rakesh Menon on February 03, 2010 at 11:04 AM IST #

great very neat !

Posted by lpainferoce on February 08, 2010 at 06:24 AM IST #

thank you so much :)

Posted by interviewz on February 15, 2010 at 06:06 AM IST #

I have problem and I write my question in oracle mix. I send all project and information. Please help me ...

Link :https://mix.oracle.com/questions/130298-upload-image-does-not-work

Posted by odayibasi on March 21, 2010 at 03:55 PM IST #

@odayibasi I'm not able to access oracle-mix from office, I'll check it once am home. I hope below post will be of help..

http://blogs.sun.com/rakeshmenonp/entry/javafx_upload_file

Posted by Rakesh Menon on March 23, 2010 at 02:41 AM IST #

Hi Rakesh,

This is a fantastic application thank you very much for sharing it with us.

But I was having a problem I don't know if you could help me with it? I used your main.fx file in NetBeans and the application works fine. However when I changed it to run in a browser the download function doesn't seem to work?

I got this error from the Java Console:
Exception in thread "AWT-EventQueue-28" java.security.AccessControlException: access denied (java.io.FilePermission C:\\Users\\Lee\\AppData\\Roaming\\Microsoft\\Windows\\Recent read)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkRead(Unknown Source)
at java.io.File.exists(Unknown Source)
at java.io.Win32FileSystem.canonicalize(Unknown Source)
at java.io.File.getCanonicalPath(Unknown Source)
at sun.awt.shell.Win32ShellFolderManager2.createShellFolder(Unknown Source)
at sun.awt.shell.Win32ShellFolderManager2.getRecent(Unknown Source)
at sun.awt.shell.Win32ShellFolderManager2.get(Unknown Source)
at sun.awt.shell.ShellFolder.get(Unknown Source)
at sun.swing.WindowsPlacesBar.<init>(Unknown Source)
at com.sun.java.swing.plaf.windows.WindowsFileChooserUI.updateUseShellFolder(Unknown Source)
at com.sun.java.swing.plaf.windows.WindowsFileChooserUI.installComponents(Unknown Source)
at javax.swing.plaf.basic.BasicFileChooserUI.installUI(Unknown Source)
at com.sun.java.swing.plaf.windows.WindowsFileChooserUI.installUI(Unknown Source)
at javax.swing.JComponent.setUI(Unknown Source)
at javax.swing.JFileChooser.updateUI(Unknown Source)
at javax.swing.JFileChooser.setup(Unknown Source)
at javax.swing.JFileChooser.<init>(Unknown Source)
at javax.swing.JFileChooser.<init>(Unknown Source)
at testfile.Main$1.lambda(Main.fx:94)
at testfile.Main$1.invoke(Main.fx:93)
at testfile.Main$1.invoke(Main.fx:93)
at javafx.scene.control.Button.fire(Unknown Source)
at com.sun.javafx.scene.control.ButtonBaseBehavior.mouseRelease(Unknown Source)
at com.sun.javafx.scene.control.caspian.AbstractButtonSkin$4.lambda(Unknown Source)
at com.sun.javafx.scene.control.caspian.AbstractButtonSkin$4.invoke(Unknown Source)
at com.sun.javafx.scene.control.caspian.AbstractButtonSkin$4.invoke(Unknown Source)
at javafx.scene.Node.impl_processMouseEvent(Unknown Source)
at javafx.scene.Node.preprocessMouseEvent(Unknown Source)
at javafx.scene.Scene$MouseHandler.process(Unknown Source)
at javafx.scene.Scene$MouseHandler.process(Unknown Source)
at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
at com.sun.javafx.tk.swing.SwingScene$SwingScenePanel.doMouseEvent(Unknown Source)
at com.sun.javafx.tk.swing.SwingScene$SwingScenePanel.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at com.sun.embeddedswing.EmbeddedEventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Posted by Lee on March 31, 2010 at 07:34 PM IST #

@Lee Thanks! When its executed in browser (Applet), it runs in sandbox, and won't have access to file system by default - "access denied java.io.FilePermission" - so you need to sign application so that user can grant permission to access file-system (for download & save). This can be done from your project properties. Select "Self Signed Jar" option.

Posted by Rakesh Menon on April 01, 2010 at 04:12 AM IST #

@Rakesh,

It worked! Thank you very much your a legend!

Posted by Lee on April 01, 2010 at 05:01 PM IST #

@Lee Glad! Thanks! :)

Posted by Rakesh Menon on April 05, 2010 at 03:57 AM IST #

Post a Comment:
Comments are closed for this entry.
About


The views expressed on this blog are my own and do not necessarily reflect that of my organization

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today