medusa
medusa copied to clipboard
medusa-file-s3: Use an existing bucket?
I already have an S3 bucket that is connected to CloudFront to use as a CDN for my site. I'm adding Medusa to that site. I'd like to use that existing bucket, but place all Medusa media in a subfolder. Is that possible?
I think the only missing piece to be able to do this is a plugin configuration option to specify a static prefix to add at the beginning of each file key. A prefix like 'medusa/' would put all of those files in a separate 'folder' in your s3 bucket. It's a quite simple change that won't impact people who choose not to use the option. I will do a PR for it.
@jordanlambrecht – did you try strengths with it before filing the issue?
I believe it is doable :)
@pevey, I imagine adding it to your bucket plugin configuration would suffice, but I might be wrong.
E.g. if you have an existing S3 bucket website
, you would have the following S3 plugin configuration:
{
resolve: "medusa-file-s3",
options: {
bucket: "website/medusa",
...
},
},
I could test it out, but I feel pretty sure that would break the initial establishment of the client. The sdk s3 client constructor function would fail because the bucket does not exist.
@pevey Wow, that was fast. Thank you for doing that. Should we update the documentation as well?
After/if the PR is merged, would you maybe want to take a stab at doing a PR to update the README for the package and the docs? It could be a great first issue for getting started contributing to Medusa, and it could probably be done directly on GitHub without setting up the monorepo on your local machine.
@pevey @jordanlambrecht did you test whether or not this is already supported through the bucket
configuration?
s3 buckets are not designed to work that way. You can mimic a directory-like structure, but under the hood, it is not designed that way at all. Adding "folders" has to be done through the file key, not the bucket name. I tested it out so that you can see the specific error messages.
By default: S3_BUCKET="laroastingco-products"
Test 1:
S3_BUCKET="laroastingco-products/test/"
Error:
Test 2:
S3_BUCKET="laroastingco-products-test"
Error:
I would like to bring something else regarding this issue. In larger projects, where we manage more types of assets then just product images, place all files on the bucket root (as is today) it's not a option. We need to be able to specify exactly where the files will be placed. So, could be a good idea to allow upload and download functions to have a path
to base it.
Something like this:
uploadFile(file, options = { isProtected: false, acl: undefined, path?: string }) {
const parsedFilename = parse(file.originalname)
const fileName = `${parsedFilename.name}-${Date.now()}${parsedFilename.ext}`
const fileKey = options.path ? `${options.path}/${fileName}` : fileName
// Now days: const fileKey = `${parsedFilename.name}-${Date.now()}${parsedFilename.ext}`
const params = {
ACL: options.acl ?? (options.isProtected ? "private" : "public-read"),
Bucket: this.bucket_,
Body: fs.createReadStream(file.path),
Key: fileKey,
}
return new Promise((resolve, reject) => {
this.client_.upload(params, (err, data) => {
if (err) {
reject(err)
return
}
resolve({ url: data.Location, key: data.Key })
})
})
}
I could probably do it myself, just let me know if you guys are interested in having it. As far as I can see it should not introduce any breaking changes.