Ionic2 rc cordova filetransfer plugin with heroku issues


#1

Hello all,

I got a strange issues with ionic 2 RC. All this NEVER happen in ionic2 beta11.

I use Cordova fileTransfer plugin upload photo to the Heroku python flask backend. The application in ionic2 beta 11 working nicely.

Once I update to ionic2 RC when I update the photo, I always get 503, which in Heroku h18 error code.

By the way: it only on android. iOS work perfectly.

Someone has the simulate issues?

Thanks


#2

Can you share the code you’re using on both the front end, and the backend?


#3

@ihadeed Thanks for the quick reply! And I found the issues. It is not relative with ionic2 RC at all.
It is the bug from the Cordova file plugin and Cordova file transfer plugin.
Because I update the Cordova-plugin-file from 4.2.0 to 4.3.0 and Cordova-plugin-file-transfer from 1.5.1 to 1.6.0 and the issues is raise to the android.

Now I downgrade that two plugin. And everything is back to normal. I don’t know why. but I will ask them.


#4

I had this app that used FileTransfer to upload pictures to AWS S3 … after upgrading to rc0 it stopped working properly. AWS didn’t like that the plugin was sending an unrecognized header (Transfer-Encoding) even though I set chunkedMode: false.

I went through the changes that happened in cordova-plugin-file-transfer to see if anything has changed in regards to that header… but I couldn’t find anything. So I didn’t bother downgrade to an older version of the plugin. I ended up modifying my picture upload process so that I would be sending the file to my Express app, and the express app would then upload it to S3 …

I should’ve stopped being lazy and downgraded the plugin just to see what happens :grin:


#5

Hey, I had the same path like you to find what happen. And I’m more interest in how you modified your upload process? :slight_smile:


#6

Ok so instead of the old proces:

  • Call API and Get signed URL
  • Upload to S3
  • Notify my API that upload is complete and provide image url to save

I am doing the following now:

  • Upload file to API
  • API then uploads it to S3 and saves it

It’s much easier to deal with, it just uses more server resources but it’s not really a big deal unless if you have a file sharing website.

So on the front end, I’m still using the FileTransfer plugin, since it works well if I’m just dealing with my own server. The only difference (as I mentioned earlier) is that now I upload files directly to my own server instead of the 3-step upload. I only changed the settings so that it uses POST instead of PUT, and I added field name, so it posts it as a form (multipart form submission).

On the back-end, I had to install multer which is a middleware for Express that handles file uploads. Multer can parse various types of file uploads and then it sets req.files property for you. Similar to how express-jwt and similar libraries set the req.user property.

Step 1: I created a file that I can import from any file in my API, because I have multiple routes that accept photo uploads and I don’t want to create multiple instances of multer:

import * as multer from 'multer';
export default multer({
    dest: 'tmp/',
    limits: {
        fields: 0,
        fieldSize: 5000000
    }
});

Step 2: Again, since I’m uploading from different routes, it makes sense to make a helper function that handles the upload to S3, so I created the following:

export class ImageUploader {

    static uploadImage(key: string, filePath: string): Promise<string> {
        return new Promise<string>((resolve, reject) => {
            let s3 = new aws.S3();
            fs.readFile(filePath, (err, data) => {
                if(err) return reject(err);
                s3.upload({
                    Bucket: 'MY_BUCKET_NAME',
                    Key: key, // file path + name
                    Body: data, // this is the image data
                    ACL: 'public-read' // permissions for anyone to read
                }, (err, r) => {
                    // delete temporary file after we're done uploading
                    fs.unlink(filePath); // fs is from require('fs'), built into nodejs
                    if(err) reject(err);
                    else {
                        resolve(r.Location); // resolve the file public URL
                    }
                });
            });
        });
    }

}

Step 3: I did the following in my route page (this is a simplified version of what’s actually happening)

import Upload from '../incudes/multer.ts'; // this is the file above
import { ImageUploader } from '../services/image-uploader.ts'; // the static class above

function updateAvatar(req, res) {

       let updateDoc = (url?: string) => {
            User.findByIdAndUpdate(req.auth.user_id, {avatar: url}, (err, doc) => {
                if(err) Utils.res(res, 400); // my helper function that handles responses
                else Utils.res(res); // my helper function that handles responses
            });
        };

        let file = req.file;
        // the user wishes to delete their saved avatar
        if(!file) return updateDoc(null);

        // TODO check mime types, size.. etc


        // this is the `key` value for S3
        // it's basically the path + file name to store the image at
        let file_name = 'avatars/' + req.auth.user_id + '/' + Date.now() + '.jpg';

        // call our helper function to upload the file
        ImageUploader.uploadImage(file_name, file.path)
            .then((url) => {
                updateDoc(url);
            })
            .catch(e => {
                console.log(e);
                Utils.res(res, 400); // my helper function that handles responses
            });
}

I hope that helped :slight_smile:


#7

Hey. It the solution before for my project. So right now once I downgrade la Cordova file transfer plugin. My old flow is working good. Anyway. Thanks for the share! :slight_smile: