JavaFX – Upload and Download Large Files
June 16, 2009 19 Comments
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
The application downloads a larger version of the photo. I took it from Somnathpur using Nikon Coolpix!
|
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:





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?
@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.
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)
@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
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.
@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.
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 )
@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
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.
@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.
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.
@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)?
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
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?
@Mark This depends on how the server is implemented. I can provide another sample including a simple server side jsp/servlet.
@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.
Pingback: JavaFX – Upload File « Rakesh Menon
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 =]
…
Sure.. I’ll write one.. I no longer have access to JavaFX supported mobile phones, so not in a position to try.. I’ll try with emulator..