File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Servlets and the fly likes POSTing from applet to servlet Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Servlets
Bookmark "POSTing from applet to servlet" Watch "POSTing from applet to servlet" New topic
Author

POSTing from applet to servlet

Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hello. If somebody has a minute, I have been working on an applet-servlet contraption that will post a file a user selects via signed applet to a shared drive on the http server's network. The applet establishes an HTTPUrlConnection with the servlet and writes the file in bytes to the httprequest object. My problem is that when the servlet creates an InputStream from the request object and reads it, it reads only 5520 bytes and cuts off. It happens for any file I send, 5520 bytes appears to be some kinda limitation on the httprequest object. If anybody has any input on this, I'd appreciate it. Thank you very much for reading and for your time.
Tom Katz
Ranch Hand

Joined: Aug 19, 2002
Posts: 169
Can you post the code that is stopping after 5520 bytes. We send larger byte arrays than that in an applet->servlet setup. Here's the way I did it:

Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hello. I've done some additional tinkering wiht this. I checked the http response code in the applet and it gives an internal server error (code 500) when attempting to write in excess of 5520 bytes into the httprequest object (although it will post the 5520 already written in). I also checked the available bytes in the servlet on the httprequest object and it gives 5520 bytes. For any files smaller than 5520 bytes, ie text files, no error is given, the files post to completion, and 200 is the http response code. I'll keep messing with it but if somebody has any ideas regarding a potential 5520 byte limitation on httprequest objects, I would appreciate it. Thank you for reading again.
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hi Tom. THank you vedry much for reading my post or whatever. Ok, here is what the applet is doing...

FileInputStream inputFileStream = new FileInputStream(path);

URL url = new URL("http://...);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/binary");

HttpURLConnection hc = (HttpURLConnection)(connection);
hc.setRequestMethod( "POST" );

OutputStream os = hc.getOutputStream();

byte[] ByteArray = new byte[(int)imgFileSize];

// READ THE INPUT FILE STREAM INTO BYTE ARRAY AND GET THE END NUM OF BYTES
int numBytes = inputFileStream.read(ByteArray);
int offset = 0;

while (numBytes > 0) {
System.out.println("numBytes is " + numBytes);
// WRITE FIRST CHUNK TO OS , FROM 0 TO NUMBYTES, THEN FOLLOWING CHUNKS
os.write(ByteArray, offset, numBytes);

// GET NEXT CHUNK SIZE
numBytes = inputFileStream.read(ByteArray);
offset = offset + numBytes;
}
os.flush();

int respCode = hc.getResponseCode();
System.out.println("respCode is " + respCode);

// When done close the streams
inputFileStream.close();
os.close();

....

I kinda noticed that ObjectOutputStream object and writeObject method in your code thing. I don't remember seeing that class before but I'll check it out...
[ December 07, 2005: Message edited by: Tom Griffith ]
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12835
    
    5

If this was my problem I would make that >= 0 because only a -1 signals the end of the stream, a 0 simply means no more data AT THIS TIME - maybe it is waiting for the next TCP/IP block.
Bill
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hi everybdoy. THank you again for reading this. Yeah, I was kinda thinking about that yesterday (0 as opposed to -1) but I never had a problem inserting oracle blobs via network tcp/ip and it appears that the appropriate number of bytes is being written into the outputstream from the HttpURLCOnnection...

I added a couple of prints inside the applet...


while (numBytes >= 0) {

System.out.println("numBytes is " + numBytes);

// WRITE FIRST CHUNK TO OS , FROM 0 TO NUMBYTES, THEN FOLLOWING CHUNKS
os.write(ByteArray, offset, numBytes);

// GET NEXT CHUNK SIZE
numBytes = inputFileStream.read(ByteArray);

System.out.println("numBytes2 is " + numBytes);

offset = offset + numBytes;
}


selecting a jpg of 22390 bytes, the following prints to the console...

numBytes is 22390
numBytes2 is -1

The -1 indicates that everything (22390 bytes) is written into the ouputstream for the HttpURLCOnnection on the first pass in the loop. Maybe the "bottleneck" is the request object itself and only 5520 bytes can get rammed into it.

I did try to change the numBytes from > 0 to >= as you suggest Bill, in both the applet and the servlet (although only 5520 bytes ever reaches the servlet) and it yields the same result. I've yet to try the ObjectOutputStream as Tom posted so I'll mess with that this afternoon. I don't know, something seems too "neat and tidy" about this 5520 byte number..like it's some kinda overridable default...thank you very much again for reading and for any suggestions or whatever...
[ December 08, 2005: Message edited by: Tom Griffith ]
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hi. No dice with ObjectOutputStream either. The httprequest still appears to be cut off at 5520 bytes and I get a response code of 500 (internal server error). I checked the config file for the j2ee server to see if this has something to do with some threshold or setting, but I don't see anything.
[ December 08, 2005: Message edited by: Tom Griffith ]
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12835
    
    5
Maybe the "bottleneck" is the request object itself and only 5520 bytes can get rammed into it.

No, the request object just provides access to the input stream - there is no intrinsic size limit on the input stream.
Bill
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hi Bill. Yeah, I found that out last night. I ran a test where I deployed the app to my localhost. The applet, although now loaded from localhost, is still the same as before and still connects to the "real" server based servlet via URL and HttpURLConnection. When the applet is loaded from localhost as oppsed to the server, all the bytes are sent successfully in the request.

The only difference is where the applet loads from. If from the server, only 5520 bytes are received by the servlet...if applet is loaded from localhost, all bytes are received and processed by the servlet.

I also discovered that the server, NT based, is currently running in safe mode (pending virus protection software installation). Maybe thats messing with the applet, but I can't really see how since applets run locally. It's really weird or whatever...but again, the only difference is from where the applets loads ~from~...
[ December 09, 2005: Message edited by: Tom Griffith ]
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hello. jsut an fyi for whomever might be following or whatever, the applet loaded from the localhost is now streaming only 5520 bytes to the servlet. At least it's now consistent...
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12835
    
    5
Are you absolutely sure that ALL exceptions are being caught and reported on both the applet and servlet side? Maybe some vital clue is being discarded.
Bill
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hi Bill. The streams in both the applet and servlet are created, read, written, etc inside try blocks that catch Exception. The exception I do get on the servlet is an out of bounds exception due to passing the file size as a parameter and using this value to set up the length of the byte array that will be read/written into the outputstream. While the servlet reads the input stream, once that magic 5520 bytes is exceeded, it goes out of bounds and raises the error. Other than that I get nothing that I can trace that explains the truncation to 5520 bytes...especially when the applet indicates all the bytes are written into the httprequest to completion.

Oh, I might have mentioned it before, but at the beginning of the servlet, i.e. the first line inside doPost, the avaliable() method is called on the inputstream and it always gives 5520. The applet and servlet throw no other exceptions other than the out of bounds mentioned above. I keep going back to this safe mode on nt. There must be something restricting this and not raising alarm bells in either the applet or servlet. Unfortunately I'm not able to take it off safe mode at the moment.
[ December 12, 2005: Message edited by: Tom Griffith ]
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12835
    
    5
If you are getting an array out of bounds exception writing into an array created with this line:

Then I immediately suspect that imgFileSize is not what you think it is.

You didn't use the result of the available() method did you? That only refers to the immediately available byte count in the buffer.

If you want the servlet to know the file size, set the request header "Content-length" in the applet and read it in the servlet.
Bill
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Bill, the file size in the applet is sent to the servlet via request parameter...

long file_size_long = file.length();

String file_size = String.valueOf(file_size_long);

...

URL url = new URL("http://test_server/test_app/Servlet?file_size="+file_size);

...

(still inside the applet, the file is read and written into the ouputstream from the servlet)

...

byte[] ByteArray = new byte[(int)file_size_long];

int numBytes = inputFileStream.read(ByteArray);

int offset = 0;

while (numBytes >= 0) {
System.out.println("numBytes is " + numBytes);
os.write(ByteArray, offset, numBytes);
numBytes = inputFileStream.read(ByteArray);
offset = offset + numBytes;
}

when the applet completes, the last line I see written on the console is "numBytes is -1", indicating all of ByteArray, of length file_size_long, was written to the servlet.

Does this look about right? I think setting the request header would accomplish the same thing and yield the same result...inexplicable truncation to 5520 bytes between applet and servlet...

As far as available() in the servlet, I put that in to see how much was available to the servlet. I was hoping to see the full file size, but it always yields 5520, unless the file is < 5520 bytes, then it shows the entire size. As stated above, I am trying to use the file_size request parameter as the imgFileSize variable...

from the servlet:

String file_size_parameter = request.getParameter("file_size");

long imgFileSize = Long.parseLong(file_size_parameter);


I am given some pause about this available() method. When the servlet reads the inputstream, how could it ever be guaranteed to read all the bytes in a stream at any given time if available() can return anything less than the full number of bytes?

Thank you very much again for hanging around with this or whatever.
[ December 13, 2005: Message edited by: Tom Griffith ]
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12835
    
    5
once that magic 5520 bytes is exceeded, it goes out of bounds and raises the error

As I recall, the ArrayIndexOutOfBounds exception reports the actual index that caused the exception. What is it reporting?
how could it ever be guaranteed to read all the bytes in a stream at any given time if available() can return anything less than the full number of bytes?

Recall that between your servlet and the applet, TCP/IP has turned the applet stream into packets - these packets are being turned back into a stream on the servlet side. Your servlet has to adapt to the fact that on any one attempt to read, zero, 1 or many packets may be available, or the last packet may have been read.
Bill
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
Hi Bill. I'll check out the servlet side and see what I can do about handling packets or whatever. I'm seeing the same phenomena on a second server but instead of 5520 bytes, it's reading something like 8270. I'll have to see how I can code the servlet to handle bytes incrementally or whatever...I am going to do some testing with isavailable() but it sounds as though this number can be ~anything~ at any moment while the servlet runs. This is getting kinda complex.
[ December 16, 2005: Message edited by: Tom Griffith ]
Tom Griffith
Ranch Hand

Joined: Aug 06, 2004
Posts: 275
hi. I just wanted to thank everybody for your time and help. I was able to get this thing working thanks to this thread. I hadn't accounted for bytes to be read in packets inside the servlet, it was just reading the first packet as Bill pointed out. SO I set the InputStream inside a loop that will access whatever is available at the moment and then it sets that chunk to the InputStream. Just to follow up for future reference for anybody, here is roughly how I coded doPost in the servlet...


InputStream is;

OutputStream os;

String file_size_text = request.getParameter("file_size");

...insert other file specific parameters here to use as metadata...

long imgFileSize = Long.parseLong(file_size_text);

long total_processed = 0;

// SET OS = NEW FILEOUTPUTSTREAM, ETC....

while (total_processed < imgFileSize) {



try {

is = request.getInputStream();

byte[] ByteArray = new byte[is.available()];

int numBytes = is.read(ByteArray);
int offset = 0;

System.out.println("Bytes available to be processed now - " + numBytes);

// WRITE THE CURRENT PACKET TO OS
os.write(ByteArray, offset, numBytes);

// OK, THAT CHUNK IS WRITTEN, GET TOTAL BYTES WRITTEN SO FAR...

total_processed = numBytes + total_processed;

System.out.println("Total bytes processed to this pt - " + total_processed);

} catch (Exception e) {
System.out.println(e);
// END TRY BLOCK
}


// END WHILE LOOP
}

os.flush();

// When done close the streams
is.close();
os.close();
System.out.println("finished");

}

}
[ December 21, 2005: Message edited by: Tom Griffith ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: POSTing from applet to servlet