File Uploads - edgee:slingshot - still good? better options?

I’ve used edgee:slingshot before - probably back around 2015… It was fantastic!

Fast forward to now and I have a requirement to handle uploads again.
That package hasn’t been updated since 2016.
I don’t want to get caught out with a package which might fail with a future Meteor updates.

Does anyone know if it is still maintained? Perhaps are there better ways to handle uploads in 2021?

1 Like

I’m using ostrio files (The trusted source for JavaScript packages, Meteor resources and tools | Atmosphere) and for me is very good.


I’ve recently used this fork of edgee:slingshot without any issue.


Still using the original slingshot without any issues.


What exactly is the difference of the backtobikes fork? Other than it’s being “revived”, but looking for maintainers?

1 Like

Yeah I was wondering the same thing - the readme doesn’t seem to mention any changes/updates.

This is great to hear, I might just run with it again to see how I like it.

Same here, Meteor Files is very stable and reliable and constantly maintained


We are using Meteor Files. This is very reliable and well maintained (support is very efficient).


Question for those using S3.

Do you use signed URLs to access the uploaded files to S3 - or just the direct bucket URL?
In my previous usage of slingshot the files being uploaded were not private, but in my current project this would be ideal.

AFIK slingshot and meteor-files do not support this out of the box. But it would be easier to achieve this with meteor-files.

The only advantage of slingshot over meteor-files is that it allows client-side uploads.

1 Like

Client side upload is a big one though.

I am looking into the AWS documentation, don’t think it should matter either way (slingshot or meteor files). Just wondering if anyone has successfully implemented it :slight_smile:

We are using evaporatejs GitHub - TTLabs/EvaporateJS: Javascript library for browser to S3 multipart resumable uploads

1 Like

We have 2 new maintainers for slingshot (myself included), we’ll get started soon, it would be worth considering this as something to add


That is great to hear.
Right now has there been any modification to your fork of slingshot?
I am using the other library and it works fine.

We ended up rolling our own version of slingshot specifically for AWS to support multi part uploads (and by extension retries) but we needed support for > 5gb uploads. Implementing the signing is not trivial and AWS’ documentation on this isn’t great (the case of the variable names is critical and not always documented correctly) and it’s not always the incorrect request that fails, but the final “complete” request.

We then use either CloudFront to connect with signed policy cookies (more efficient than directly signing each url) or custom per session temporary credentials for direct s3 access (CloudFront doesn’t support encrypted s3 objects sadly). The url signing is pretty easy.

We currently use slingshot for client side uploads and it do have private uploads, you can just set the param per directive. Then we just get signed urls from the server after validating that user has permission to access the file.

Just putting Slingshot out there to our users and I thought it was great! Great docs and makes for writing clean code to handle uploads

I needed this in a non-Meteor project recently, and found that it’s actually pretty easy to create a signed URL using the s3 NPM packages now:

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'

const client = new S3Client({
  region: 'eu-west-3',
  credentials: {
    accessKeyId: process.env.S3_ACCESS_ID as string,
    secretAccessKey: process.env.S3_ACCESS_KEY as string,

const command = new PutObjectCommand({
  Bucket: 'yourbucket',
  Key: key,
  ContentType: 'image/png',
  ACL: 'public-read', // change this if you don't want the file to be public

const url = await getSignedUrl( client, command )

When you have the URL on the client, it’s a simple matter of doing:

await fetch( url, { method: 'PUT', body })