8

Currently, we are using aws-sdk v2, and extracting uploaded file URL in this way

  const res = await S3Client
    .upload({
      Body: body,
      Bucket: bucket,
      Key: key,
      ContentType: contentType,
    })
    .promise();

  return res.Location;

Now we have to upgrade to aws-sdk v3, and the new way to upload files looks like this

const command = new PutObjectCommand({
  Body: body,
  Bucket: bucket,
  Key: key,
  ContentType: contentType,
});

const res = await S3Client.send(command);

Unfortunately, res object doesn't contain Location property now.

getSignedUrl SDK function doesn't look suitable because it just generates a URL with an expiration date (probably it can be set to some extra huge duration, but anyway, we still need to have a possibility to analyze the URL path)

Building the URL manually does not look like a good idea and a stable solution to me.

humkins
  • 9,635
  • 11
  • 57
  • 75
  • 3
    I'm running into this problem too and unfortunately, I think building the URL manually is the only solution here. – mAAdhaTTah Sep 07 '21 at 18:41

2 Answers2

7

Answering myself: I don't know whether a better solution exists, but here is how I do it

const command = new PutObjectCommand({
  Body: body,
  Bucket: bucket,
  Key: key,
  ContentType: contentType,
});

const [res, region] = await Promise.all([
  s3Client.send(command),
  s3Client.config.region(),
]);

const url = `https://${bucket}.s3.${region}.amazonaws.com/${key}`
humkins
  • 9,635
  • 11
  • 57
  • 75
  • Probably a good idea to call `encodeURI` on the `key` as well. – John Cummings Feb 27 '22 at 22:18
  • You mean `https://s3.${region}.amazonaws.com/${bucket}/${key}`? – aghidini Mar 18 '22 at 09:03
  • 2
    It looks like a step back respect to SDK v2. Are they forcing us to make an additional request to get the official object URL? – Delmo Apr 13 '22 at 17:37
  • 2
    @aghidini it depends on whether you want virtual-hosted or path styled URL https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html – humkins Apr 15 '22 at 13:26
  • @humkins you are right, I was getting SSL certificate errors using the "new" virtual-hosted styled URL but probably I messed up something else – aghidini Apr 16 '22 at 13:25
2

You can use Upload method from "@aws-sdk/lib-storage" with sample code as below.

import { Upload } from "@aws-sdk/lib-storage";
import { S3Client } from "@aws-sdk/client-s3";

const target = { Bucket, Key, Body };
  try {
    const parallelUploads3 = new Upload({
      client: new S3Client({}),
      tags: [...], // optional tags
      queueSize: 4, // optional concurrency configuration
      leavePartsOnError: false, // optional manually handle dropped parts
      params: target,
    });

    parallelUploads3.on("httpUploadProgress", (progress) => {
      console.log(progress);
    });

    await parallelUploads3.done();
  } catch (e) {
    console.log(e);
  }

Make sure you return parallelUploads3.done() object where you will get location in the return object as below

S3 Upload Response

Reference

  1. https://stackoverflow.com/a/70159394/16729176
Onion Lim
  • 21
  • 2