How to upload files to Amazon S3 with Angular 2 and Webpack

One recurrent question lately is: How the **** do I magically teleport files to AWS S3 using Angular 2?

Fear not! Here is the answer!

Installation

I’m using the stack from angular2-webpack-starter(How to install it Here) because it’s fast and preconfigured so adapt this tutorial to your case.

aws-sdk is not WebPack’s best friend so some work need to be done.

Thankfully, Andrew H Farger  did the work for us here :D.

You will have a small warning saying that it’s precompiled. No big deal.

Now we are going to prevent errors from parsing and typings.

In Webpack dev conf add :

In src/custom-typings.d.ts, add:

Let’s Code Now

You need to use the pre-compiled version of aws-sdk in dist otherwise you will have some errors.

In your component file, import aws-sdk:

In the template, just a file input, which on change will trigger fileEvent with the event:

Get the AWSService from Window since AWS dist’s puts it there and Voila! You have your AWS S3 ready to be loaded.

A very simple fileEvent method in the class.

Get the files ->  select the first one -> configure AWS -> create a new S3 object and finally upload using this object and display the results.

It’s as simple as this. Don’t hesitate to comment if you need some help with your config :).

Subscribe to my mailing list to get access to a Free 7-day Ionic 3 introduction email course!
100% Privacy. I'll never spam you!

You might be interested in this analyze of the full-stack project created by the Ionic and AWS teams, many services from the new AWS Mobile Hub are detailed: AWS S3, Cognito, DynamoDB.

PS: I wrote this article with a focus on using AWS with Angular 2 and Webpack. In the comments you’ll see how to make it secure by signing your credentials server-side with a Base64 policy.

24 Comments

  1. Anthony Anthony
    May 24, 2016    

    And like that everyone have your access to your s3 credentials… not such a good idea, except if this is just for an angular executed in server side but i really don’t think so.
    The best solution is to generate a signed request via a backend application which can access credentials safely and then return this signed request to the client and send the request to upload the file to s3 with this signed request and the file, bonus you can (and should) constraint this to your website using CORS configuration from s3.

    Exemple to generate the signed request for s3 in nodejs

    const aws = require(‘aws-sdk’);

    module.exports = function create(req, res) {
    aws.config.update({
    accessKeyId: process.env.AWS_ACCESS_KEY,
    secretAccessKey: process.env.AWS_SECRET_KEY
    });
    const params = {
    Bucket: process.env.S3_BUCKET,
    Key: req.query.file_name,
    Expires: 60,
    ContentType: req.query.file_type,
    ACL: ‘public-read’
    };
    (new aws.S3()).getSignedUrl(
    ‘putObject’,
    params,
    (err, data) => {
    const response = err || {
    signed_request: data,
    url: `https://${process.env.S3_BUCKET}.s3.amazonaws.com/${req.query.file_name}`
    };
    if (err) res.status(400);
    return res.json(response);
    }
    );
    };

    • Matthieu Drula Matthieu Drula
      May 24, 2016    

      I totally agree with the server side security.
      I used in the past https://github.com/asafdav/ng-s3upload but no module available at the moment for angular 2(it would be a good idea to make one).
      This tutorial is just a piece of informations, after that the way you integrate it in your code is yours, I don’t cover security or how to configure AWS S3 for CORS, there are sooo many great tutorials out there.

    • Benedikt Benedikt
      May 24, 2016    

      Is the file this way uploaded to the backend first?
      I would like to avoid that… Is there any way to not upload the file to the backend and then to AWS but directly to AWS, in a secure mode though?

      • Matthieu Drula Matthieu Drula
        May 25, 2016    

        Following the informations from https://github.com/asafdav/ng-s3upload
        Setup – 4
        It depends of your backend technology.
        In JS something like this:

        var S3SecretAccessKey = config.getS3SecretAccessKey()
        var policy = { "expiration": "2060-12-01T12:00:00.000Z",
        "conditions": [
        {"acl": "public-read" },
        {"bucket": "ice" },
        ["starts-with", "$filename", ""],
        ["starts-with", "$key", ""]
        ]
        }
        var stringPolicy = JSON.stringify(policy);
        var base64Policy = Buffer(stringPolicy, "utf-8").toString("base64");

        // sign the base64 encoded policy
        var signature = crypto.createHmac("sha1", S3SecretAccessKey)
        .update(Buffer(base64Policy, "utf-8")).digest("base64");

        // build the results object
        var s3Credentials = {
        policy: base64Policy,
        signature: signature
        };
        res.send(s3Credentials)

  2. Benedikt Benedikt
    May 24, 2016    

    Thanks for this article. Although this seems kind of a hack, like you should never edit something in /node_modules/…
    I am hosting on Heroku, node_modules are installed on deployment, so editing in /node_modules/ won’t help. You have any idea of another possible solution?

    • Matthieu Drula Matthieu Drula
      May 24, 2016    

      You are welcome, you are right for node_modules.
      This is only because I don’t master my stack yet.
      I decided to hack it and share if someone had the same trouble.
      I thought that it would be better for everybody to share the knowledge on that topic and not be like ‘Well as long as my Webpack doesn’t work I’ll do nothing even if it takes forever’ (You know THIS guy :P).
      One thing that I have seen back in the days was to upload all your node_modules to Heroku, not that awesome but still an option, another way would be to fork aws-sdk.
      They are working to make it Webpack friendly: https://github.com/aws/aws-sdk-js/issues/603

  3. May 26, 2016    

    Greetings! I’ve been reading your website for some time now
    and finally got the courage to go ahead and give
    you a shout out from Huffman Tx! Just wanted to mention keep
    up the great work!

    • Matthieu Drula Matthieu Drula
      May 26, 2016    

      Wow, thank you very much.

  4. May 30, 2016    

    Good day! This is my first visit to your blog! We are a group of
    volunteers and starting a new initiative in a community in the same niche.
    Your blog provided us beneficial information to work on. You have done a outstanding job!

    • Matthieu Drula Matthieu Drula
      May 30, 2016    

      Welcome to the family :).

  5. m88 m88
    June 12, 2016    

    Hi! Would you mind if I share your blog with my facebook group?

    There’s a lot of folks that I think would really enjoy your content.
    Please let me know. Thank you

    • Matthieu Drula Matthieu Drula
      June 13, 2016    

      Sure, share the love!

  6. zaier zaier
    August 4, 2016    

    This is not secure this is dangerous I would not recommend this for real world application.
    You have to sign your uploadLinks from your backend https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html

    • Matthieu Drula Matthieu Drula
      August 7, 2016    

      You are totally right, I wrote this article focusing more on how to use AWS with Angular 2 and Webpack, we then discussed about the security and I wrote the whole signing process (May 25th).
      I’ll add a PS in the article.

  7. August 18, 2016    

    Thank you for sharing your thoughts. I truly appreciate your efforts and I
    will be waiting for your next write ups thank you once again.

  8. September 23, 2016    

    Very nice article, just what I wanted to find.

  9. vinit vinit
    October 5, 2016    

    I’m following quickstart tutorial for angular 2…when I use the above example..it stops with error: “Property ‘AWS’ does not exist on type ‘Window’.

  10. Jaume Vidal Jaume Vidal
    December 20, 2016    

    What do you think on using Cognito or Auth0 Delegation to fetch temporal credentials with a limited role ?

    The browser holds in memory credentials that expire every hour and are fetched dynamically during login with either STS or Auth0 delegate API, very much like getting a session cookie.

    AWS articel here http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/s3-example-photo-album.html

    No Web server required

Leave a Reply

Your email address will not be published. Required fields are marked *

2 Shares