views:

111

answers:

2

Hi, I am trying to send image from my midlet to an HTTP server. images are converted into byte and sent to server using http multipart/form-data request format.

ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(boundaryMessage.getBytes());
bos.write(fileBytes);
bos.write(endBoundary.getBytes());

When the image size is less than around 500Kb then the code works fine, but when the size is greater than it shows: Uncaught exception java.lang.OutOfMemoryError. I tried using Java ME SDK 3.0 and Nokia S40 5th edition FP1. Any help is greatly appreciated. Thanks for looking

I used the following class file: click here

+2  A: 

Being forced to read the whole file into memory with the first `getFileBytes(), in order to transmit in one piece, is most likely what's running the system out of memory.

Find a way to read about 100K, transmit it, then read another 100, until the whole file is done.

The HttpMultipartRequest class's constructor as written allows only for the transmission of the file as one single object. Even though it's an implementation of the MIME multipart content protocol, it is limited to the case of transmitting just one part:

The class can be modified to allow sending multiple parts. Have a look at the protocol specification RFC1341, especially the example half-way through.

With these three lines together as they are in the constructor, the whole file is sent in one part;

bos.write(boundaryMessage.getBytes());
bos.write(fileBytes);
bos.write(endBoundary.getBytes());

But in the multipart case, there needs to be multiple boundaries, before the endBoundary:

 for(bytes=getMoreFileBytes(); ! bytes.empty; bytes=getMoreFileBytes()){
        bos.write(boundaryMessage.getBytes());
        bos.write(bytes);
    }
    bos.write(endBoundary.getBytes());

As a quick fix, let the constructor open the file and read it 100k at a time. It already receives a fileName parameter.

The PHP script on the other end, should reassemble the original file from the pieces.

Frayser
I tried to reply to your comment but it shows negative character, please see my reply below
newcomer
A: 

I am not very familiar with the forum rules, I tried to comment your answer but it shows negative.

Okay.. Now I am getting java.io.IOException: Persistent connection dropped after first chunk sent, cannot retry

previously I tried to use application/x-www-form-urlencoded request type with Base64 encoding using kidcandy's code here: http://forums.sun.com/thread.jspa?threadID=538500

This code divides the imagedata in chunks to avoid 'Persistent connection drop' problem and creates connection with the server using 'for' loop. The problem is maximum chunk size maybe only 500-700 bytes. So to send a 100kb image the code needs to create and close connection 200 times, I tried to run this on nokia 5310 phone, it behaves like it is hibernating... so it is not useful.

  1. Now should I use that for loop for 'multipart/form-data' request?
  2. What is the maximum chunk size for this type of request?
  3. Or any other idea? Regards
newcomer
When I first came to Stack Overflow, I was unable to comment, only answering was possible. You can comment on your own posts(the one at the top, or this one), though. Hopefully you can fix the trouble while staying with *MIMEMultipart.* I already got that code to do HTTP *POST* to Apache on my system from one of those virtual phones that came with Wireless Tool Kit. It would take me a while to analyze that other bit of code; someone there is claiming that with Apache, it's necessary to send multiple POSTS instead of one big POST with multiple parts. Might have to add those ideas.
Frayser
1. Use the *MIME Multipart content* protocol with the loop; see `DataInputStream.read(buffer,offset, length)` to read 100k at a time. 2. In this case the max data length is set by memory constraints. If 500k is too much, keep it down around 100K. 3. Since this is from scratch, there are more things to consider, for instance; once sent, it needs to be verified that the data arrived intact(checksums, reply OK or FAIL from server, retransmission on error, etc). The receiver PHP script needs to be written. WebDav or FTP would be easier; but I don't know if there is a good implementation for MID.
Frayser
I am using Apache and yes I guess it requires multiple POST request instead of big one. But it is too slow to open and close connection so frequently from a mobile device. I thought if in MIME Multipart content protocol the chunk size were big enough like 100K then for 1Mb it would be considerable to use a for loop. What kidcandy did in receiver side is he kept all the image chunk data in a txt file sequentially and later created an image from those raw data and deleted that file on the server side. in contrary for one big multipart POST i received image just using $_FILE[] variable.
newcomer
I am suffering this trouble for few days now.. please let me know if you find a good implementation for midlets. many thanks
newcomer
As far as I can tell, Multi-part Content works with Apache. After modified as discussed, that HttpMultipartRequest class was able to send a file piecemeal, and the PHP script received and recreated the image at the other end. [Want to test it](http://www.frayser.org/Answers/so/MultipartSend.tar.gz) on a real device?
Frayser
That was great, I was able to send an Image of 624KB. But when I tried to send a 1.3MB Outofmemory error is back in action again! (SDK Nokia S40 5th edition FP1) Its coming from that loop. I guess outputstream accumulates all the imagedata in device buffer or heapmemory(?) which overflows... let me know what do you think.
newcomer
Another strange thing is, when I use J2ME SDK 3.0 and Apache on my system it works fine but when I put the uploadscript on the live server it returns only the empty string "uploaded file size is <empty> bytes" with nothing uploaded etc etc. I am confused
newcomer
I didn't notice [add/show new] 2 more comments button for 2 days. Contact me by email, see the "contact information" link on the home page of the website. I'm going to take a look at this later. I hope you already tried using a smaller chunk size; it was a 100K, I believe.
Frayser
[Updated code](http://www.frayser.org/Answers/so/MultipartSend.zip): This does `read`, `write`, and `flush` in a tight loop creating a minimal amount of garbage to be collected. Seems to keep total memory usage under 500K when sending a 1.6M file. The tar file was refreshed, too; but it is a full GIT repository.
Frayser