Discussion:
OutOfMemoryError: how best to transfer large video files into a byte array?
Anna PS
2010-04-08 20:58:43 UTC
Permalink
Apologies for cross-posting with StackOverflow, but I'm getting a bit
desperate. I'll cross-post any final answer too.

Please could anyone suggest an approach for transferring a >2MB video
from a ContentResolver into a Bytestream, without running out of
memory?

See question: http://stackoverflow.com/questions/2599305/android-outofmemoryerror-while-uploading-video-how-best-to-chunk

Here's the current code, which throws an OutOfMemoryError on the
byteBuffer.write(buffer, 0, len) line when transferring large videos:

// get bytestream to upload
videoByteArray = getBytesFromFile(cR, fileUriString);

public static byte[] getBytesFromFile(ContentResolver cR, String
fileUriString) throws IOException {
Uri tempuri = Uri.parse(fileUriString);
InputStream is = cR.openInputStream(tempuri);
byte[] b3 = readBytes(is);
is.close();
return b3;
}
public static byte[] readBytes(InputStream inputStream) throws
IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
// this is storage overwritten on each iteration with bytes
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Abdul Mateen
2010-04-08 21:02:59 UTC
Permalink
It tried very much on this, but I had to gave up, it seems not possible as
far as I think, lets get the experts reply.
Post by Anna PS
Apologies for cross-posting with StackOverflow, but I'm getting a bit
desperate. I'll cross-post any final answer too.
Please could anyone suggest an approach for transferring a >2MB video
from a ContentResolver into a Bytestream, without running out of
memory?
http://stackoverflow.com/questions/2599305/android-outofmemoryerror-while-uploading-video-how-best-to-chunk
Here's the current code, which throws an OutOfMemoryError on the
// get bytestream to upload
videoByteArray = getBytesFromFile(cR, fileUriString);
public static byte[] getBytesFromFile(ContentResolver cR, String
fileUriString) throws IOException {
Uri tempuri = Uri.parse(fileUriString);
InputStream is = cR.openInputStream(tempuri);
byte[] b3 = readBytes(is);
is.close();
return b3;
}
public static byte[] readBytes(InputStream inputStream) throws
IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
// this is storage overwritten on each iteration with bytes
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Mark Murphy
2010-04-08 21:16:15 UTC
Permalink
Post by Anna PS
Apologies for cross-posting with StackOverflow, but I'm getting a bit
desperate. I'll cross-post any final answer too.
Please could anyone suggest an approach for transferring a >2MB video
from a ContentResolver into a Bytestream, without running out of
memory?
1. Why are you using a ContentProvider?

2. What are you doing with the >2MB byte array when you get it on the
ContentResolver side?

My hope is that there's a way to avoid the problem altogether.
--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://twitter.com/commonsguy

Android App Developer Books: http://commonsware.com/books
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Anna PS
2010-04-08 21:23:02 UTC
Permalink
Post by Mark Murphy
1. Why are you using a ContentProvider?
Because that seemed to be the best way to get from a content URI
(returned from the Android video camera intent) to a byte stream.
Happy to do it another way, though.
Post by Mark Murphy
2. What are you doing with the >2MB byte array when you get it on the
ContentResolver side?
Once I've got the videoByteArray, I'm uploading it to a server, as a
FilePart within a multipart message. I can post the code for that if
it would be useful.

It works well for files of less than 2MB.
Post by Mark Murphy
My hope is that there's a way to avoid the problem altogether.
That would be good :) If anyone can work it out, it's probably you!
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Abdul Mateen
2010-04-08 21:31:27 UTC
Permalink
I got the same problem, when I uploaded the videos to Facebook, I have got
the same issue while uploading big files, have you found any workarround,
even I flushed the outstream on every read. but it did not also seems be the
solution.
Post by Anna PS
Post by Mark Murphy
1. Why are you using a ContentProvider?
Because that seemed to be the best way to get from a content URI
(returned from the Android video camera intent) to a byte stream.
Happy to do it another way, though.
Post by Mark Murphy
2. What are you doing with the >2MB byte array when you get it on the
ContentResolver side?
Once I've got the videoByteArray, I'm uploading it to a server, as a
FilePart within a multipart message. I can post the code for that if
it would be useful.
It works well for files of less than 2MB.
Post by Mark Murphy
My hope is that there's a way to avoid the problem altogether.
That would be good :) If anyone can work it out, it's probably you!
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To unsubscribe from this group, send email to
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Mark Murphy
2010-04-08 21:35:05 UTC
Permalink
Post by Anna PS
Post by Mark Murphy
1. Why are you using a ContentProvider?
Because that seemed to be the best way to get from a content URI
(returned from the Android video camera intent) to a byte stream.
Happy to do it another way, though.
Oh. I thought you had perhaps written the ContentProvider in question.
Post by Anna PS
Once I've got the videoByteArray, I'm uploading it to a server, as a
FilePart within a multipart message. I can post the code for that if
it would be useful.
It works well for files of less than 2MB.
I suspect your problem is not in reading the InputStream, but rather in
how FilePart does what it does. Since that isn't part of Android, it was
probably developed without tight memory constraints in mind. If you hand
it 1 KB chunks each time, it is probably going to allocate a 1 KB byte
array, then a 2 KB byte array, then a 3 KB byte array, then a 4 KB byte
array, and so on. You are hopelessly fragmenting your heap. Not to
mention that FilePart might well wind up Base64 encoding the result,
requiring another massive memory allocation.

I would recommend rewriting your Web server. Use HTTP PUT instead of
HTTP POST with multipart. Better yet, use HTTP PUT and support chunking
on the Web server -- you do a PUT for every 1MB or so and the server
stitches them together.

If this is not your Web server, you're pretty much screwed AFAICT. Doing
bigger chunks than 1 KB will help somewhat, and rewriting FilePart to
minimize reallocations will help somewhat, but you'll still probably not
get much past, say, 5MB that way.
--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://twitter.com/commonsguy

Android Training in NYC: 30 April-2 May 2010: http://guruloft.com
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Anna PS
2010-04-08 21:52:23 UTC
Permalink
Post by Mark Murphy
I suspect your problem is not in reading the InputStream, but rather in
how FilePart does what it does. Since that isn't part of Android, it was
probably developed without tight memory constraints in mind. If you hand
it 1 KB chunks each time, it is probably going to allocate a 1 KB byte
array, then a 2 KB byte array, then a 3 KB byte array, then a 4 KB byte
array, and so on. You are hopelessly fragmenting your heap. Not to
mention that FilePart might well wind up Base64 encoding the result,
requiring another massive memory allocation.
OK, I see. Although, I do get the OutofMemoryError on the
byteBuffer.write(buffer, 0, len), well before I do anything with the
FilePart.

Do you think that even if I managed to fix the byteBuffer issue, I'd
still hit problems when I got to FilePart?
Post by Mark Murphy
I would recommend rewriting your Web server. Use HTTP PUT instead of
HTTP POST with multipart. Better yet, use HTTP PUT and support chunking
on the Web server -- you do a PUT for every 1MB or so and the server
stitches them together.
It is my Web server, so I can rewrite it to accept a PUT request. Are
you suggesting that I do something like this, for each 1MB of the
data?

HttpPut httpPut = new HttpPut(url);
httpPut.setEntity(new StringEntity(data));

I'll try it and let people know here (and on Stack Overflow!) how it
goes.

Thank you for the advice, as ever :)
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Jason Proctor
2010-04-08 22:02:51 UTC
Permalink
Post by Anna PS
It is my Web server, so I can rewrite it to accept a PUT request. Are
you suggesting that I do something like this, for each 1MB of the
data?
HttpPut httpPut = new HttpPut(url);
httpPut.setEntity(new StringEntity(data));
I'd use ByteArrayEntity.
what about streaming it with InputStreamEntity?

ideally you'd never have those 2mb cached at one time.
--
jason.vp.engineering.particle
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Mark Murphy
2010-04-08 22:00:52 UTC
Permalink
Post by Anna PS
OK, I see. Although, I do get the OutofMemoryError on the
byteBuffer.write(buffer, 0, len), well before I do anything with the
FilePart.
That doesn't make sense. What are you doing with the 1 KB you read in
each time? I assumed you were feeding that into the FilePart.
Post by Anna PS
It is my Web server, so I can rewrite it to accept a PUT request. Are
you suggesting that I do something like this, for each 1MB of the
data?
HttpPut httpPut = new HttpPut(url);
httpPut.setEntity(new StringEntity(data));
I'd use ByteArrayEntity.
--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://twitter.com/commonsguy

Android Training in US: 14-18 June 2010: http://bignerdranch.com
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Anna PS
2010-04-08 22:12:33 UTC
Permalink
Post by Mark Murphy
Post by Anna PS
OK, I see. Although, I do get the OutofMemoryError on the
byteBuffer.write(buffer, 0, len), well before I do anything with the
FilePart.
That doesn't make sense. What are you doing with the 1 KB you read in
each time? I assumed you were feeding that into the FilePart.
Not directly - the videoByteArray is used for the FilePart once I have
the whole thing, like this:

videoByteArray = getBytesFromFile(cR, fileUriString);
FilePart videoFile = new FilePart("fileupload", new
ByteArrayPartSource(
"fileupload", videoByteArray));
videoFile.setContentType("video/3gpp");
videoFile.setCharSet(null);
Part[] parts = {
new StringPart("name", name),
videoFile };

But I get the error on the first line of that code, in the readBytes
that's called from getBytesFromFile.

I guess this is all academic if I need to rewrite it to use HttpPut,
anyway...
Post by Mark Murphy
Post by Anna PS
It is my Web server, so I can rewrite it to accept a PUT request. Are
you suggesting that I do something like this, for each 1MB of the
data?
   HttpPut httpPut = new HttpPut(url);
   httpPut.setEntity(new StringEntity(data));
I'd use ByteArrayEntity.
Thanks.

To ask a dumb question, as someone who hasn't used chunked uploading
before: how can I indicate to the server the order in which to glue
the chunks back together? (Tell me to go away and ask a Java forum if
you want.)
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Mark Murphy
2010-04-08 22:24:45 UTC
Permalink
:: smacks forehead ::

This is why I really shouldn't try to answer questions when I'm
seriously short on sleep.
Post by Anna PS
But I get the error on the first line of that code, in the readBytes
that's called from getBytesFromFile.
Actually, you get it from the ByteArrayOutputStream. It's the one
fragmenting your memory, as it has to keep reallocating its space, 1 KB
at a time.

Change bufferSize to be much bigger, like 1 MB, and see what that gets
you. You're still not going to get much past 5 MB or so, but you might
get past 2 MB.
Post by Anna PS
To ask a dumb question, as someone who hasn't used chunked uploading
before: how can I indicate to the server the order in which to glue
the chunks back together? (Tell me to go away and ask a Java forum if
you want.)
If you're designing your own protocol, you do it however you want.
You'll need some sort of identifier to indicate that all these PUT
operations are part of the same upload. So, for example, you could send
a final GET request to indicate "we're done uploading" for that identifier.
Post by Anna PS
what about streaming it with InputStreamEntity?
ideally you'd never have those 2mb cached at one time.
If HttpClient supports streamed HTTP PUT operations, you're right --
this might allow an upload in one step, without chunking. That's
definitely worth a shot and is a great idea!
--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://twitter.com/commonsguy

_The Busy Coder's Guide to *Advanced* Android Development_
Version 1.4 Available!
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Jason Proctor
2010-04-08 22:30:17 UTC
Permalink
Post by Mark Murphy
Post by Anna PS
To ask a dumb question, as someone who hasn't used chunked uploading
before: how can I indicate to the server the order in which to glue
the chunks back together? (Tell me to go away and ask a Java forum if
you want.)
If you're designing your own protocol, you do it however you want.
You'll need some sort of identifier to indicate that all these PUT
operations are part of the same upload. So, for example, you could send
a final GET request to indicate "we're done uploading" for that identifier.
i tried using chunked uploads some time ago and ran into all kinds of
problems with common web servers. some servers regarded each chunk as
a separate request, others required a content-length for the upload
(despite the fact that chunked by definition is for content whose
length you don't necessarily know at upload time), etc etc. at least
a year or so ago, madness lay within chunkedness.
Post by Mark Murphy
Post by Anna PS
what about streaming it with InputStreamEntity?
ideally you'd never have those 2mb cached at one time.
If HttpClient supports streamed HTTP PUT operations, you're right --
this might allow an upload in one step, without chunking. That's
definitely worth a shot and is a great idea!
i use HttpPut happily with setEntity(StringEntity). if it doesn't
work with setEntity(InputStreamEntity), it's a bug IMHO.

InputStreamEntity is the way to go with this, again IMHO.
--
jason.vp.engineering.particle
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Bob Kerns
2010-04-08 23:19:28 UTC
Permalink
I'm a bit puzzled why the other respondents didn't pick up this, maybe
I missed something in the discussion?

But anyway, the basic flaw in your strategy is reading it all into
memory at once. There's no need to do so, and that is ALWAYS going to
impose a limit on the size of file you can handle, on any platform.

Instead of reading all your data, and then stufffng it into a
ByteArrayOutputStream, and pulling out a *HUGE* array --

The simplest strategy: Open an output stream to your server, and
simply copy from the camera to the server.

That has the fatal drawback that the camera will be tied up, and
possibly blocked, if the server is too slow -- which is likely. So
that's not really a viable strategy. So you need something to stand in
for the server. The only viable option is a file on the SD card.

So open a temporary output file, rather than a byte-array output
stream, and write it there. Then, instead of getting a byte array, re-
open your SD card file, and copy from that file to the server.

Under no circumstances, in no programing environment, do you ever want
to buffer a file of unknown size in memory.

If you wanted to be extremely clever, you could simultaneously
transfer to the SD card, and transfer from the SD card to the net. But
extreme cleverness is seldom very smart.

I wonder why the multipart stuff was left out of the SDK? I hadn't
noticed that. These little holes and omissions and using-obsolete-
versions thing I find rather disorienting -- you think you know what's
there, then BAM -- not on the Android, unless you BYO Code.
Post by Anna PS
Apologies for cross-posting with StackOverflow, but I'm getting a bit
desperate. I'll cross-post any final answer too.
Please could anyone suggest an approach for transferring a >2MB video
from a ContentResolver into a Bytestream, without running out of
memory?
See question:http://stackoverflow.com/questions/2599305/android-outofmemoryerror-w...
Here's the current code, which throws an OutOfMemoryError on the
// get bytestream to upload
videoByteArray = getBytesFromFile(cR, fileUriString);
public static byte[] getBytesFromFile(ContentResolver cR, String
fileUriString) throws IOException {
    Uri tempuri = Uri.parse(fileUriString);
    InputStream is = cR.openInputStream(tempuri);
    byte[] b3 = readBytes(is);
    is.close();
    return b3;}
public static byte[] readBytes(InputStream inputStream) throws
IOException {
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
    // this is storage overwritten on each iteration with bytes
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];
    int len = 0;
    while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
    }
    return byteBuffer.toByteArray();
}
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To unsubscribe from this group, send email to
For more options, visit this group athttp://groups.google.com/group/android-developers?hl=en
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Mark Murphy
2010-04-08 23:40:44 UTC
Permalink
Post by Bob Kerns
I'm a bit puzzled why the other respondents didn't pick up this, maybe
I missed something in the discussion?
But anyway, the basic flaw in your strategy is reading it all into
memory at once. There's no need to do so, and that is ALWAYS going to
impose a limit on the size of file you can handle, on any platform.
I didn't miss it. OTOH, I was trying to scope my response into something
that didn't mess up the original plan too much and stuck to things I
knew worked with HttpClient. And, as previously noted, I'm short on
sleep. :-(
Post by Bob Kerns
That has the fatal drawback that the camera will be tied up, and
possibly blocked, if the server is too slow -- which is likely.
I'm reasonably certain the Uri being handed back from the Intent will be
to a file handled by the MediaStore, not live off the camera.
Post by Bob Kerns
I wonder why the multipart stuff was left out of the SDK?
It's an oft-asked question with no known answer.
--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://twitter.com/commonsguy

Android 2.x Programming Books: http://commonsware.com/books
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Gubatron
2010-04-09 16:26:52 UTC
Permalink
Why are you reading the entire file into a byte array?
That sounds right there like the OutOfMem error.

public static byte[] getBytesFromFile(ContentResolver cR, String
fileUriString) throws IOException {
Uri tempuri = Uri.parse(fileUriString);
InputStream is = cR.openInputStream(tempuri);
byte[] b3 = readBytes(is);
is.close();
return b3;
}

when you're about to do your multipart post just read a little, write
a little.
Buffer the sending process, you don't need to do multiple PUTs or
POSTS (and rewrite your webserver)
Post by Mark Murphy
Post by Bob Kerns
I'm a bit puzzled why the other respondents didn't pick up this, maybe
I missed something in the discussion?
But anyway, the basic flaw in your strategy is reading it all into
memory at once. There's no need to do so, and that is ALWAYS going to
impose a limit on the size of file you can handle, on any platform.
I didn't miss it. OTOH, I was trying to scope my response into something
that didn't mess up the original plan too much and stuck to things I
knew worked with HttpClient. And, as previously noted, I'm short on
sleep. :-(
Post by Bob Kerns
That has the fatal drawback that the camera will be tied up, and
possibly blocked, if the server is too slow -- which is likely.
I'm reasonably certain the Uri being handed back from the Intent will be
to a file handled by the MediaStore, not live off the camera.
Post by Bob Kerns
I wonder why the multipart stuff was left out of the SDK?
It's an oft-asked question with no known answer.
--
Mark Murphy (a Commons Guy)http://commonsware.com|http://twitter.com/commonsguy
Android 2.x Programming Books:http://commonsware.com/books
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To unsubscribe from this group, send email to
For more options, visit this group athttp://groups.google.com/group/android-developers?hl=en
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

To unsubscribe, reply using "remove me" as the subject.
Anna Powell-Smith
2010-04-09 16:43:42 UTC
Permalink
Post by Gubatron
Why are you reading the entire file into a byte array?
That sounds right there like the OutOfMem error.
Because it's the only way that I know to get from a content Uri to the byte
array that I use to create the FilePart element of the multipart message.

It is possible to create the FilePart element using a File object (this
handles even a 50MB file successfully, though it takes around half an hour
to create, so I don't fancy using it in practice). However, I can't work
from a File object, because I have to use the content Uri that is returned
by ACTION_VIDEO_CAPTURE. Originally I did pass a File Uri as extra output to
ACTION_VIDEO_CAPTURE, but that unfortunately breaks the 'retake' and
'delete' buttons on the video camera.
Post by Gubatron
when you're about to do your multipart post just read a little, write
a little. Buffer the sending process,
Thanks, but please could you explain what you mean by that? Perhaps with an
example?

Mark warned that creating buffers tends to clog up memory. Indeed, after
increasing the buffer size to 1MB, as he predicted, I can now handle files
up to about 5MB.
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

To unsubscribe, reply using "remove me" as the subject.
Gubatron
2010-04-09 17:19:37 UTC
Permalink
I suppose when you say FilePart, you mean this

org.apache.commons.httpclient.methods.multipart.FilePart

I'm thinking along these lines after looking at that API (I haven't
tested this)

final File theFile = new File("yourFileLargerThan2Mb.ext");

//Implement your own PartSource to feed your File
PartSource partSource = new PartSource() {
//this should return a buffered reader... right?
public InputStream createInputStream() {
return BufferedInputStream (new FileInputStream(theFile));
}

//implement the other methods of the interface
public String getFileName() {
return theFile.getName();
}

public long getLength() {
return theFile.length();// although this might be how much is
left on the stream, not sure.
}

}

FilePart part = FilePart(theFileName, partSource);

then use your part on your multipart request.
Post by Anna Powell-Smith
Post by Gubatron
Why are you reading the entire file into a byte array?
That sounds right there like the OutOfMem error.
Because it's the only way that I know to get from a content Uri to the byte
array that I use to create the FilePart element of the multipart message.
It is possible to create the FilePart element using a File object (this
handles even a 50MB file successfully, though it takes around half an hour
to create, so I don't fancy using it in practice). However, I can't work
from a File object, because I have to use the content Uri that is returned
by ACTION_VIDEO_CAPTURE. Originally I did pass a File Uri as extra output to
ACTION_VIDEO_CAPTURE, but that unfortunately breaks the 'retake' and
'delete' buttons on the video camera.
Post by Gubatron
when you're about to do your multipart post just read a little, write
a little. Buffer the sending process,
Thanks, but please could you explain what you mean by that? Perhaps with an
example?
Mark warned that creating buffers tends to clog up memory. Indeed, after
increasing the buffer size to 1MB, as he predicted, I can now handle files
up to about 5MB.
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

To unsubscribe, reply using "remove me" as the subject.
Anna Powell-Smith
2010-04-09 18:35:01 UTC
Permalink
Post by Gubatron
I suppose when you say FilePart, you mean this
org.apache.commons.httpclient.methods.multipart.FilePart
I'm thinking along these lines after looking at that API (I haven't
tested this)
final File theFile = new File("yourFileLargerThan2Mb.ext");
//Implement your own PartSource to feed your File
PartSource partSource = new PartSource() {
//this should return a buffered reader... right?
public InputStream createInputStream() {
return BufferedInputStream (new FileInputStream(theFile));
}
//implement the other methods of the interface
public String getFileName() {
return theFile.getName();
}
public long getLength() {
return theFile.length();// although this might be how much is
left on the stream, not sure.
}
}
FilePart part = FilePart(theFileName, partSource);
then use your part on your multipart request.
Thanks. Constructing a FilePart from a File is actually as easy as this, I
think - but do you think your method would provide some advantage?

File temp_file = new File(Environment.getExternalStorageDirectory(),
"myfile.gif");
FilePart vFile = new FilePart("fileupload", temp_file);

As I say, this works for files of 50MB. The only reason I can't use it is
that I can't construct a File object from an Android content Uri. I have to
use an Android content Uri because that's what the video intent returns.
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

To unsubscribe, reply using "remove me" as the subject.
Anna Powell-Smith
2010-04-09 18:49:08 UTC
Permalink
Post by Anna Powell-Smith
Post by Gubatron
I suppose when you say FilePart, you mean this
org.apache.commons.httpclient.methods.multipart.FilePart
I'm thinking along these lines after looking at that API (I haven't
tested this)
final File theFile = new File("yourFileLargerThan2Mb.ext");
//Implement your own PartSource to feed your File
PartSource partSource = new PartSource() {
//this should return a buffered reader... right?
public InputStream createInputStream() {
return BufferedInputStream (new FileInputStream(theFile));
}
//implement the other methods of the interface
public String getFileName() {
return theFile.getName();
}
public long getLength() {
return theFile.length();// although this might be how much is
left on the stream, not sure.
}
}
FilePart part = FilePart(theFileName, partSource);
then use your part on your multipart request.
Thanks. Constructing a FilePart from a File is actually as easy as this, I
think - but do you think your method would provide some advantage?
File temp_file = new File(Environment.getExternalStorageDirectory(),
"myfile.gif");
FilePart vFile = new FilePart("fileupload", temp_file);
As I say, this works for files of 50MB. The only reason I can't use it is
that I can't construct a File object from an Android content Uri. I have to
use an Android content Uri because that's what the video intent returns.
Ah. If I could transform my content Uri into FileInputStream (will have to
experiment) then I could use your method.

I can convert a content Uri to an InputStream already, so it'll just be
getting from an InputStream to a FileInputStream that might be the
challenge. I'll experiment.
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers+***@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

To unsubscribe, reply using "remove me" as the subject.
Loading...