Search code examples
requesttitaniumappceleratorimage-uploading

Can't upload image to remote server using Appcelerator


The application I'm working uses an API developed by another team. I'm working on Titanium 2.1.2 and I'm trying to upload a photo using said API. I'm using Appcelerator's HTTPClient to make the request. Here's my code:

    var url = 'http://api.veramiko.com/albums/' + album.veramiko_id + '/photos';
    var photo = imageView.toBlob();

    var args = { //parameters sent to post photo
        file : photo,
        description : descriptionText
    };

    var client = Ti.Network.createHTTPClient({
        onload : function(e){
            Ti.API.info(this.responseText); //Print the result
        },
        onerror : function(e){
            Ti.API.error(this.responseText); //Print the result
        },
        timeout : 60000
    });
    client.open('POST', url);
    client.setRequestHeader('Authorization', 'Bearer ' + token);
    client.setRequestHeader('Content-type', "multipart/form-data");
    client.send(args);

Token is a variable we use to authorize any requests made to the server. I thought that by only converting the image from the ImageView into Blob would be enough to send the photo, but the photo isn't uploaded. The post is created with the description but the photo isn't sent properly.

Do I need to add something else? Is it right to send the photo as a Blob?

EDIT: I read this link and I tried the following with no result:

    var url = 'http://api.veramiko.com/albums/' + album.veramiko_id + '/photos';
    var boundary = '-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var photo = imageView.toBlob();

    var args = {
        file : photo,
        description : descriptionText.value
    };      

    var contentDisposition = "--" + boundary + "\r\n"; 
    contentDisposition += "Content-Disposition: form-data; name=\"file\";";
    contentDisposition += "filename=\"" + imageView.image + "\"\r\n\";";
    contentDisposition += "Content-Type: application/octet-stream\r\n\r\n";

    var fullContent = contentDisposition + photo  + "\r\n--" + boundary + "--";

    alert(JSON.stringify(args));
    var token = JSON.parse(Ti.App.Properties.getString('loggedUser', 'No existe')).networks[0].token;
    var client = Ti.Network.createHTTPClient({
        onload : function(e){
            Ti.API.info(this.responseText); //Print the result
        },
        onerror : function(e){
            Ti.API.error(this.responseText); //Print the result
        },
        timeout : 60000
    });
    client.open('POST', url);
    client.setRequestHeader('Authorization', 'Bearer ' + token);
    client.setRequestHeader('Content-Type', "multipart/form-data; boundary=\"" + boundary + "\"");
    client.setRequestHeader('Connection', 'close');
    client.send(fullContent);

I tried to wrap the file with a Content-Disposition and Content-Type header with no result.


Solution

  • I finally found a way to solve this. Please refer to the following link.

    This is how my code looked in the end:

        // I put the contents of my image into a variable
    var f = imageHolder.toImage();
        // I create a random name for the image
    var tmpName = (new Date()).getTime().toString() + '.png';
        // I create a folder where I will store the photo temporally
    var g = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'picturesToUpload');
    if (!g.exists()) {
        // If the directory doesn't exist, make it
        g.createDirectory();
    };
    var photo = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'picturesToUpload', tmpName);
        // write the contents of the image into the file
    photo.write(f);
        // I create my url with the albumId where I'll upload the picture
    var url = 'http://api.veramiko.com/albums/' + albumId + '/photos';
    var args = {
        file : photo.read(), // I read the contents of the file
        description : ''
    }
    var token = JSON.parse(Ti.App.Properties.getString('loggedUser', 'No existe')).networks[0].token;
    var client = Ti.Network.createHTTPClient({
        onload : function(e){
            Ti.API.info('Info received from the uploading: ' + this.responseText);
        },
        onerror : function(e){
            Ti.API.debug('Error: ' + this.responseText);
        },
            timeout : 60000
    });
    client.open('POST', url);
        // these headers are important
    client.setRequestHeader('enctype', 'multipart/form-data');
    client.setRequestHeader('Content-Type', 'image/png');
    client.setRequestHeader('Authorization', 'Bearer ' + token);
    client.send(args);
    

    Hope this info helps more people.