HTTPClient memory leak when downloading large files, using FileStream instead?

You must Login before you can answer or comment on any questions.

Similar memory leak problem like in:

http://developer.appcelerator.com/question/81381/httpclient-memory-leak

http://developer.appcelerator.com/question/28911/httpclient-leaks-easily-or-can-we-have-a-close-method

My mobile application downloads large PDF files and shows them to the user. However, HTTPClient causes memory leaks.

Could it be possible to use the new FileStream with the HTTPClient to read and write 1k chunks to avoid memory problems?

http://developer.appcelerator.com/blog/2011/05/titanium-mobile-intro-series-streams.html

EDIT: Solved! Using BlobStream did the trick since responseData is a TiBlob object.

3 Answers

Accepted Answer

couple of things:

when you use the "onload" event, you already have the entire date, so why not use Titanium.Filesystem.getFile and .write method to write the content to the file?

Second, when using large data (and downloading in general), use the (undocumented) method setFile:

var c = Titanium.Network.createHTTPClient({timeout:10000});
 
var filename = 'test.pdf';
var f = Titanium.Filesystem.getFile(Titanium.Filesystem.externalStorageDirectory, filename); 
// I use applicationDataDirectory on iOS instead
 
if (!f.exists()) {
 
    try {
 
        c.onload = function(){
                showPDF(f);
        };
 
        c.ondatastream = function(e){
        };
 
        c.onerror = function(e){
            Ti.API.info('XHR Error ' + e.error);
        };
 
        var downloaduri = 'http://www.domain.com/test.pdf';
 
        // open the client
        c.open('GET', downloaduri);
        c.setFile(Titanium.Filesystem.externalStorageDirectory + "/" + filename);
        // send the data
        c.send();
 
    } catch (e) {
        Ti.API.info("Error", Titanium.API.error);
    }
}
setFile should appear before send and after the open method. It will save the contents of the call to the file path you specified, without it saving the responseData in the object, leading to a HUGE memory save.

— answered 2 years ago by Yaniv Nagar
answer permalink
2 Comments
  • This is not working for me, I'm getting an error in the console "Failed to move file from 'X' to 'Y'"

    — commented 2 years ago by Kevin Southworth

  • .setFile() is not supported on Android, documentation confirms it. I've tested on the latest SDK 2.0.x and it's still not supported.

    — commented 1 year ago by Jimmy Forrester-Fellowes

OK, a simple example:

var c = Titanium.Network.createHTTPClient({timeout:10000});
 
var filename = 'test.pdf';
var f = Titanium.Filesystem.getFile(Titanium.Filesystem.externalStorageDirectory, filename); 
// I use applicationDataDirectory on iOS instead
 
if (!f.exists()) {
 
    try {
 
        c.onload = function(){
 
            if (c.readyState == 4) {
 
                var instream = Titanium.Stream.createStream({
                    mode: Titanium.Stream.MODE_READ,
                    source: this.responseData
                });
 
                var outstream = f.open(Titanium.Filesystem.MODE_WRITE);
 
                // Create a buffer for chunking the data.
                var buffer = Ti.createBuffer({length: 1024});
 
                // Read and write chunks.
                var read_bytes = 0;
                while ((read_bytes = instream.read(buffer)) > 0) {
                    outstream.write(buffer, 0, read_bytes);
                }
 
                // Cleanup.
                instream.close();
                outstream.close();
 
                showPDF(f);
            }
        };
 
        c.ondatastream = function(e){
        };
 
        c.onerror = function(e){
            Ti.API.info('XHR Error ' + e.error);
        };
 
        var downloaduri = 'http://www.domain.com/test.pdf';
 
        // open the client
        c.open('GET', downloaduri);
 
        // send the data
        c.send();
 
    } catch (e) {
        Ti.API.info("Error", Titanium.API.error);
    }
}

Your Answer

Think you can help? Login to answer this question!