I backed with the topic so hot on Ionic2 forum. How to upload a file to S3 bucket from ionic 2 application?

To upload Photo to s3, need to config from 2 side (backend & frontend). In this topic I only talk about frontend.

What infos we need config to upload ?

To upload from frontend. Backend serve should define for you API to get s3Signature.

This is params what s3 need:

key: [key value is configured from frontend],
AWSAccessKeyId: [AWSAccessKeyId value received from backend],
acl: [acl value received from backend],
policy: [policy value received from backend],
signature: [signature value received from backend],

Ionic2 provide FileTransfer to upload image. To use it should install this plugin

$ ionic cordova plugin add cordova-plugin-file-transfer
$ npm install --save @ionic-native/file-transfer

In this topic I suggest we should create a service for upload. (it mean create new provider for upload)

ionic g provider UploadService

In the uploadService provider. Defined the code like below. Should read code as well

import { Inject, Injectable } from '@angular/core';
import { Http, RequestOptions, Headers } from '@angular/http';
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer';
import { File } from '@ionic-native/file';

@Injectable()
export class UploadServiceProvider {
  apiUrl = `${your host to get api}`
  constructor(public http: Http, @Inject(EnvVariables) public envVariables, private transfer: FileTransfer, private file: File) {
  }

  //config S3 params
  s3UploadConfig(file, s3Params) {
    return{
      url: s3Params.bucket_name,
      method: 'POST',
      chunkedMode: false,
      headers: {
        connection: "close"
      },
      params : {
        key: `uploads/${file.substr(file.lastIndexOf('/')+1)}`,
        AWSAccessKeyId: s3Params.key,
        acl: s3Params.acl,
        policy: s3Params.policy,
        signature: s3Params.signature,
        'Content-Type' : "image/jpeg"
      }
    };
  }

  // Get Signature
  generateSignature(token) {
    const headers: Headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Accept', 'application/json');
    headers.append('Authorization-Token', token);

    const options: RequestOptions = new RequestOptions();
    options.headers = headers;
    // Call API to get Signature
    return this.http.get(`${this.apiUrl}/generate-signature`, options)
  }

  // Upload Image to s3
  upload(file,token): Promise<any>{
    return new Promise((resolve, reject) => {
      this.generateSignature(token)
        .map(response => response.json().data)
        .subscribe(
          response => {
            let s3Params = response;
            let serveConfig = this.s3UploadConfig(file, s3Params);
            let key = `uploads/${file.substr(file.lastIndexOf('/')+1)}`;
            const fileTransfer: FileTransferObject = this.transfer.create();

            fileTransfer.upload(file, encodeURI(s3Params.bucket_name), serveConfig)
              .then((result) => {
                // when finished upload photo. S3 will return a link of image.
                // This link is combined from `s3Params.bucket_name + key`
                resolve(s3Params.bucket_name + key);
              }, (error) => {
                resolve(error.json());
              });
          });
    });
  }

}

Take a look code in above. You can see what I defined:

  • (1) Function config S3 params

  • (2) Function to call API generate-signature to get Signature.

  • (3) Function for upload photo on S3.

(1) & (2) quite easy to understand, isn’t it? (if not put your comments, i will help)

  • At (3) Why I returned Promise?

    • We use service to upload and when you call it in controller or another service etc. you possible get promise as well.

Alright, Done. Above is the way to you upload photo via S3.

Read comment code to understand more

^___^

Jany Mai