AWS S3 Heroku nodejs - node.js

I am running a nodejs application hosted on heroku where I want to be able to upload selected photos to AWS S3. I followed all the steps heroku gave, but am finding this error: "MissingRequiredParameter: Missing required key 'Bucket' in params"
Here's my code:
index.js
app.get('/sign-s3', (req, res) => {
const s3 = new aws.S3();
const fileName = req.query['file-name'];
const fileType = req.query['file-type'];
console.log(fileName, fileType)
const s3Params = {
Bucket: S3_BUCKET,
Key: fileName,
Expires: 60,
ContentType: fileType,
ACL: 'public-read'
};
s3.getSignedUrl('putObject', s3Params, (err, data) => {
if (err) {
console.log(err);
return res.end();
}
const returnData = {
signedRequest: data,
url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}`
};
res.write(JSON.stringify(returnData));
res.end();
});
});
app.post('/save-details', (req, res) => {
res.send(req.body.username)
console.log(req.body.username)
});
here's my front end scripts
testing.ejs
<input type="file" id="file-input">
<p id="status">Please select a file</p>
<img style="border:1px solid gray;width:300px;" id="preview" src="/images/default.png">
<h2>Your information</h2>
<form method="POST" action="/save-details">
<input type="hidden" id="avatar-url" name="avatar-url" value="/images/default.png">
<input type="text" name="username" placeholder="Username"><br>
<input type="text" name="full-name" placeholder="Full name"><br><br>
<hr>
<h2>Save changes</h2>
<input type="submit" value="Update profile">
</form>
<script>
/*
Function to carry out the actual PUT request to S3 using the signed request from the app.
*/
function uploadFile(file, signedRequest, url){
const xhr = new XMLHttpRequest();
xhr.open('PUT', signedRequest);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4){
if(xhr.status === 200){
document.getElementById('preview').src = url;
document.getElementById('avatar-url').value = url;
}
else{
alert('Could not upload file.');
}
}
};
xhr.send(file);
}
/*
Function to get the temporary signed request from the app.
If request successful, continue to upload the file using this signed
request.
*/
function getSignedRequest(file){
const xhr = new XMLHttpRequest();
xhr.open('GET', `/sign-s3?file-name=${file.name}&file-type=${file.type}`);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4){
if(xhr.status === 200){
const response = JSON.parse(xhr.responseText);
uploadFile(file, response.signedRequest, response.url);
}
else{
alert('Could not get signed URL.');
}
}
};
xhr.send();
}
/*
Function called when file input updated. If there is a file selected, then
start upload procedure by asking for a signed request from the app.
*/
function initUpload(){
const files = document.getElementById('file-input').files;
const file = files[0];
if(file == null){
return alert('No file selected.');
}
getSignedRequest(file);
}
/*
Bind listeners when the page loads.
*/
(() => {
document.getElementById('file-input').onchange = initUpload;
})();
</script>
hopefully this helps, and thanks in advance.

Related

File not uploading in Express JS using Multer received fro Editor

I am getting the file using TinyMCE Editor. Using the paste plugin and uploading it using Express Server. I have tried using different things. But need to upload file received from TinyMCE editor
Here is my front-end Code:
function example_image_upload_handler(blobInfo, success, failure, progress) {
var xhr, formData;
localStorage.myfile = blobInfo.blob()
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', 'http://localhost:5000/api/upload');
xhr.upload.onprogress = function (e) {
progress(e.loaded / e.total * 100);
};
xhr.onload = function () {
var json;
if (xhr.status === 403) {
failure('HTTP Error: ' + xhr.status, { remove: true });
return;
}
if (xhr.status < 200 || xhr.status >= 300) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
};
xhr.onerror = function () {
failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
};
formData = new FormData();
formData.append('file', localStorage.myfile, blobInfo.filename());
xhr.send(formData);
};
const handleSubmit = async (e) => {
e.preventDefault();
console.log("hello");
example_image_upload_handler();
console.log(desc);
const newPost = {
username: user.username,
title,
desc,
};
if (file) {
const data = new FormData();
const filename = Date.now() + file.name;
data.append("name", filename);
data.append("file", file);
newPost.photo = filename;
try {
console.log("hello");
if (await axios.post("http://localhost:5000/api/upload", data)) {
// console.log("monu");
}
} catch (err) {
console.log(err);
}
}
try {
const res = await axios.post("http://localhost:5000/api/posts", newPost);
window.location.replace("/post/" + res.data._id);
} catch (err) {
console.log(err);
}
};
const handleEditorChange = (e) => {
console.log(
'Content was updated:',
setDesc(e.target.getContent())
);
}
return (
<div className="write">
{file && (
<img className="writeImg" src={URL.createObjectURL(file)} alt="" />
)}
<form className="writeForm" onSubmit={handleSubmit}>
<div className="writeFormGroup">
<label htmlFor="fileInput">
<i className="writeIcon fas fa-plus"></i>
</label>
<input
type="file"
id="fileInput"
style={{ display: "none" }}
onChange={(e) => setFile(e.target.files[0])}
/>
<input
type="text"
placeholder="Title"
className="writeInput"
autoFocus={true}
onChange={e => setTitle(e.target.value)}
/>
</div>
<Editor
apiKey="XXXXXXXXXXXXXXXXXXXXXXX"
initialValue="<p>Initial content</p>"
init={{
height: 500,
menubar: 'edit',
selector: 'textarea',
plugins: [
'advlist autolink lists link image',
'charmap print preview anchor help',
'searchreplace visualblocks code',
'insertdatetime media table paste wordcount',
'image imagetools paste'
],
images_upload_handler: example_image_upload_handler,
toolbar:
'undo redo | formatselect | bold italic | \
alignleft aligncenter alignright | \
bullist numlist outdent indent | image | help',
paste_data_images: true
}}
onChange={handleEditorChange}
/>
</div>
<button className="writeSubmit" type="submit">
Publish
</button>
</form>
</div>
);
Following is my express js upload API code:
const upload = multer({ storage: storage });
app.post("/api/upload", upload.single("file"), (req, res) => {
console.log("req");
console.log(req);
res.status(200).json("File has been uploaded");
});
Following is the error I am getting:
Please help me with the same.

Trying to send formData with another parameter via axios

I have a form that uploads single files via a FormData object. In addition to the file attribute, I want to also assign this file to a Group.
I can't figure out how to add the group object id to the request.
Here is my upload component:
<template>
<div>
<div class="ui attached segment rounded mb-3">
<form #submit.prevent="sendFile" enctype="multipart/form-data" class="ui form">
<div v-if="message" class="`message ${error ? 'text-danger' : 'text-success'}`">
<div class="message-body"> {{ message }}</div>
</div>
<div class="field">
<label for="file" class="label">Upload File</label>
<input
type="file"
ref="file"
#change="selectFile"
class="file-input"
/>
<!-- <span class="file-cta">
<span class="file-icon">
<i class="fas fa-upload"></i>
</span>
<span class="file-label">
Choose a file...
</span>
</span> -->
<span v-if="file" class="file-name">{{file.name}}</span>
<div class="field">
<button class="btn btn-info">Send</button>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: "SimpleUpload",
data() {
return {
file: "",
message: '',
error: false
}
},
computed: {
currentGroup() {
return this.$store.getters.currentGroup;
}
},
methods: {
selectFile() {
const file = this.$refs.file.files[0];
const allowedTypes = ["image/jpeg", "image/png", "image/gif"];
const MAX_SIZE = 200000;
const tooLarge = file.size > MAX_SIZE;
if (allowedTypes.includes(file.type) && !tooLarge) {
this.file = file;
this.error = false;
this.message = '';
} else {
this.error = true;
this.message = tooLarge ? `Too large. Max size is ${MAX_SIZE/1000}kb` : "Only images are allowed"
}
},
async sendFile() {
const formData = new FormData();
formData.append('file', this.file);
formData.append('group', this.currentGroup);
console.log('file is: ', this.file)
console.log('this is form data after file is added: ', formData)
try {
await axios.post('/uploads', {
formData,
group_id: this.currentGroup.id
});
console.log('this is the formData being sent: ', formData)
this.message = 'File has been uploaded';
this.file = '';
this.error = false;
} catch(err) {
this.message = err.response.data.error;
this.error = true
}
}
}
}
</script>
Here is my route in :
const Group = require('../models/Group');
const Upload = require('../models/Upload');
const router = express.Router();
const upload = require('../services/file-uploads');
const singleUpload = upload.single('file'); // has to match front end
router.post('/', auth.required, async function(req, res) {
console.log ('upload route is hit')
let results = await singleUpload(req, res, async function (err) {
if (err) {
return res.status(422).send({ errors: [{title: 'File upload error, detail: err.message'}] });
} else {
console.log('this is the upload reqest fobject: ', req);
console.log("trying to save data to postgres");
// console.log('this is the originalname of the reqest file object: ', req.file);
console.log('this is the upload reqest body: ', req.body.group_id);
await Upload.query()
.insert({
name: req.body.file.originalname,
users_id: req.user.id,
filetype: req.body.file.mimetype,
filesize: req.body.file.size,
file_url: req.body.file.location,
groups_id: req.body.group_id
})
res.json({
success: true,
message: 'ok'
});
res.json(results)
}
})
});
module.exports = router;
and the upload config in services/file-uploads:
const aws = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3');
aws.config.update({
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
region: 'us-east-1'
})
const s3 = new aws.S3();
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
} else {
cb(new Error('Invalid Mime Type, only JPEG and PNG'), false);
}
}
const upload = multer({
storage: multerS3({
s3: s3,
bucket: process.env.AWS_BUCKET,
acl: 'public-read',
metadata: function (req, file, cb) {
cb(null, {fieldName: 'TESTING_META_DATA!'});
},
key: function (req, file, cb) {
cb(null, Date.now().toString())
}
})
})
module.exports = upload;
In the request, I see body: { formData: {}, group_id: 1 },
and I can retrieve the group_id with req.body.id, but the formData object is empty
Prepare the FormData like this:
const formData = new FormData();
formData.append('file', this.file); // Append a file
formData.append('group_id', this.currentGroup.id); // Append a field
And then send it like this:
await axios({
method: 'post',
url: '/uploads',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
});

store images in postgresql from react using express multer

I'm trying to save images from my react app to backend using nodejs(express) and multer, I tried from these How to upload image using javascript fetch api and express multer
after I got the message file uploaded, how do you store it to database?
Here's the code in my react app
class UploadCover extends React.Component {
constructor(props){
super(props);
this.state={
id: this.props.location.state.id,
selectedFile : '',
imagePreviewUrl: ''
}
}
//handle image change
handleImageChange = (e) => {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () =>{
this.setState({
selectedFile:file,
imagePreviewUrl: reader.result
});
};
reader.readAsDataURL(file);
this.handleUploadCover(e.target.files[0]);
}
//upload cover
handleUploadCover = (file) => {
let form = new FormData(this.refs.myForm);
form.append('myImage', file);
fetch('http://localhost:3001/upload-cover', {
method: 'post',
header: { "Content-Type" : "application/json"},
body: form
})
.then( res =>res.json())
.then(data => console.log("data: ", data))
};
render() {
const { classes, ...rest } = this.props;
const { id, imagePreviewUrl } = this.state;
console.log("url: ", imagePreviewUrl)
let $imagePreview = null;
if(imagePreviewUrl){
$imagePreview = <img style={{width: "100%", height: "100%"}} src={imagePreviewUrl}/>;
}else{
$imagePreview = (
<div className={classes.previewText}>Please select cover</div>
);
}
return (
<div>
<HeaderHome/>
<div className={classNames(classes.main, classes.mainRaised)}>
<div className={classes.container}>
<div className={classes.storymargin}>
<h2 className={classes.title}>Upload Cover Story</h2>
<Card className={classes.uploadcontainer}>
<CardContent>
<div className={classes.imgPreview}>{$imagePreview}</div>
<form ref='myForm' encType='multipart/form-data'>
<input
accept="image/*"
className={classes.input}
id="raised-button-file"
multiple
type="file"
onChange={ e => this.handleImageChange(e)}
// ref='myForm'
/>
</form>
<label htmlFor="raised-button-file">
<Button component="span" className={classes.buttonupload}>
Choose Image
</Button>
</label>
</CardContent>
<CardActions>
<Link
to={{
pathname: "/create-chapter",
state: {id : id}
}}
>
<Button size="small" clor="primary" className={classes.buttonnextup}
onClick={ e => this.handleUploadCover(e) }
>
Next
</Button>
</Link>
</CardActions>
</Card>
</div>
</div>
</div>
<div className={classes.footer}>
<Footer />
</div>
</div>
);
}
}
and here's the backend
//set storage engine
const storage = multer.diskStorage({
destination: './public/uploads',
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
})
//Init upload
const upload = multer({
storage: storage,
limits: {fileSize: 1000000},
fileFilter: (req, file, cb) => {
checkFileType(file, cb);
}
}).single('myImage');
//Check File Type
checkFileType = (file, cb) => {
//Allowed ext
const filetypes = /jpeg|jpg|png|gif/;
//Check ext
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
//Check mime
const mimetype = filetypes.test(file.mimetype);
if(mimetype && extname){
return cb(null, true);
}else{
cb('Error: Images Only');
}
}
//upload cover story
app.post('/upload-cover', (req, res) => {
console.log('handling upload image');
upload( req, res, (err) => {
if(err){
console.log('first err', err);
res.send({
msg: err
});
}else{
if(req.file === undefined){
console.log('Error: No File Selected');
res.send({
msg: 'Error: No File Selected'
});
}else{
console.log('File Uploaded');
res.send({
msg: 'File Uploaded',
file: `uploads/${req.file.filename}`
});
}
}
});
});
and how can i send request with content type application/json and multipart/form-data at the same time through body request, I want to send form and id:this.state.id

axios upload to node.js API results in files in aws s3 becoming unreadable

Screen of UploadScreen of DownloadWhenever I utilize the client side upload panel the files that get uploaded to the bucket are named correctly but wont open. They are also a slightly different size from the front end uploaded version. I'm wondering if something in how i'm handling buffers / reading the files is off but I just started working with them yesterday so i'm fairly lost. If any of you based genius programmers could provide some insight into this issue I'd be eternally grateful!!
The overall goal is the ability to upload files to an aws s3 bucket of any file type, then be able to download these files without them being modified or rendered unopenable.
server side javascript;
var express = require("express");
var mongodb = require("mongodb");
var _ = require("lodash");
var bodyParser = require("body-parser");
var app = express();
var router = express.Router();
var mongoose = require("mongoose");
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-1'});
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
...
...
...
router.post('/upload', function (req, res) {
var file = new File({name: req.body.fileName, type: req.body.contentType, buffer: req.body.file});
var fs = require('fs');
var fileStream = fs.createWriteStream(req.body.fileName);
fileStream.write(req.body.file)
fileStream.end(function () { console.log('done'); });
fileStream.on('error', function(err) {
console.log('File Error', err);
});
fs.readFile(req.body.fileName, (err, data) => {
if (err) throw err;
console.log(data);
const params = {
Bucket: req.body.crystalName,
Key: req.body.fileName,
Body: data
};
s3.upload(params, function(s3Err, data) {
if (s3Err) {
console.log(s3Err);
} else {
res.send(`File uploaded successfully at ${data.Location}`);
console.log(`File uploaded successfully at ${data.Location}`);
}
});
});
});
client side upload function (vue.js);
<template>
<div class="main">
<input v-model="crystalName" placeholder="Crystal Name" />
<input type="file" #change="onFileChange"/>
<button v-on:click="uploadToCrystal">Upload</button>
<span>{{this.file}}</span>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'crystalviewer',
props: ['user'],
data: function () {
return {
crystalName: '',
fileName: '',
contentType: '',
file: ''
}
},
methods: {
onFileChange (file) {
let vue = this
var reader = new FileReader()
this.fileName = file.target.files[0].name || file.dataTransfer.files[0].name
this.contentType = file.target.files[0].type || file.dataTransfer.files[0].type
console.log(this.contentType)
var start = 0
var stop = file.target.files[0].size
var blob = file.target.files[0].slice(start, stop)
reader.onloadend = function (file) {
vue.file = file.target.result
}
reader.readAsText(blob, 'utf-8')
},
uploadToCrystal () {
let vue = this
axios.post('https://api.mystic-crm.com/crystalviewer/upload', {
crystalName: vue.crystalName,
fileName: vue.fileName,
contentType: vue.contentType,
file: vue.file
})
.then(response => {
console.log(response)
})
.catch(err => {
console.log(err)
})
}
}
}
</script>
<style scoped lang="less">
.main {
}
</style>
To get files after an upload run a get against;
https://api.mystic-crm.com/crystalviewer/contents/:crystalName/:fileName
where;
:crystalName = testcrystalmystic
:fileName = your_file_to_get
Turns out switching to Multiparty was the solution, now I can upload via forms. Apparently axios doesn't support file uploads but forms do so that was a fun revelation. edit added working front end
var express = require("express");
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-1'});
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
var multiparty = require('multiparty');
router.post('/upload', function (req, res) {
var form = new multiparty.Form();
var destPath;
var crystalName;
form.on('field', function(name, value) {
if (name === 'crystalName') {
crystalName = value
} else if (name === 'fileName') {
destPath = value;
}
});
form.on('part', function(part) {
s3.putObject({
Bucket: crystalName,
Key: destPath,
ACL: 'public-read',
Body: part,
ContentLength: part.byteCount
}, function(err, data) {
if (err) throw err;
console.log("done", data);
res.end("OK");
console.log("https://s3.amazonaws.com/" + crystalName + '/' + destPath);
});
});
form.parse(req);
});
front end ex;
<template>
<div class="main">
<form v-on:submit="submit">
<input name="crystalName" placeholder="Crystal Name" />
<input name="fileName" v-model="fileName" placeholder="File Name" v-show="false" />
<input name="file" type="file" #change="onFileChange"/>
<input type="submit" value="Upload File" />
</form>
</div>
</template>
<script>
export default {
name: 'crystalviewer',
props: ['user'],
data: function () {
return {
fileName: '',
modal: ''
}
},
methods: {
submit (event) {
let vue = this
var form = document.forms[0]
var request = new XMLHttpRequest()
request.open('POST', 'https://api.mystic-crm.com/crystalviewer/upload', true)
request.setRequestHeader('accept', 'multipart/form-data')
event.preventDefault()
var formData = new FormData(form)
request.send(formData)
request.onreadystatechange = function () {
if (request.readyState < 4) {
vue.modal = 'loading'
} else if (request.readyState === 4) {
if (request.status === 200 || request.status < 300) {
vue.modal = 'success'
console.log('success')
} else {
vue.modal = 'failure'
console.log('failure')
}
}
}
},
onFileChange (file) {
this.fileName = file.target.files[0].name || file.dataTransfer.files[0].name
}
}
}
</script>
<style scoped lang="less">
.main {
}
</style>
React Hooks Version for anyone searching for this
Front End:
import React, {useState} from 'react'
import axios from 'axios'
function Amazonuploadtest() {
const [file, setFile] = useState('')
const submitFile = (e) => {
e.preventDefault();
console.log(file[0])
const formData = new FormData();
formData.append('file', file);
axios.post(`http://localhost:4000/upload`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
console.log(response)
}).catch(error => {
console.log(error)
});
}
return (
<div>
<form onSubmit={submitFile} enctype="multipart/form-data" style={{paddingTop: 200}}>
<input label='upload file' type='file' name="upl" onChange={e => setFile(e.target.files[0])} />
<button type='submit'>Send</button>
</form>
</div>
);
}
export default Amazonuploadtest
Back End:
require('dotenv').config({ path: __dirname + '/.env' })
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const path = require('path')
const AWS = require('aws-sdk');
const fs = require('fs');
const multer = require('multer');
const multerS3 = require('multer-s3');
app.use(cors());
app.use(bodyParser.json());
app.use(cookieParser());
// ####################################### ALL AWS STUFF GOES HERE ###############################################################################################
AWS.config.update({
secretAccessKey: 'YOUR KEY GOES HERE',
accessKeyId: 'YOUR KEY GOES HERE',
region: 'YOUR REGION GOES HERE -> You can find it in your bucket URL',
});
const s3 = new AWS.S3();
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'YOUR BUCKET NAME -> Find it in your Bucket URL',
key: function (req, file, cb) {
cb(null, Date.now().toString() + `.png`); // gives every image upload a unique URL
}
})
});
app.post('/upload', upload.array('file',1), function (req, res, next) {
const key = req.files[0].key
console.log(key)
res.send("Uploaded!");
// We return the key here so that we can then save it as a URL in MongoDB -> allows
// you to call the image URL when rending the image on the front end.
// example -> let avatarURL = `https://s3.amazonaws.com/YOURBUCKETNAME/${key}`
});

AWS S3 & NodeJS - xhr error

I am trying follow along this tutorial on uploading files to Amazon S3 with NodeJS and have gotten hung up on an error that occurs on the client side of the code, but I'm pretty sure is part of my route. The 404 error that appears is on the xhr.send() request to the server in the sign_request function. The information from my file that is logged at the GET is correct file:138 GET http://localhost:3000/sign?file_name=gtm-value.png&file_type=image/png 404 (Not Found), which makes me think that it has something to do with my route setup.
view:
<!DOCTYPE html>
<head>
{{> app/app-head}}
</head>
<body>
{{> app/app-navigation}}
<div class="container">
<div class="col-md-12">
<form action="/create" method="post">
<input type="file" name="fileAttachment" id="image">
<img id="preview">
<button type="submit" id="button">Create Image</button>
</form>
</div>
<script type="text/javascript">
function upload(file, signed_request, url, done) {
var xhr = new XMLHttpRequest();
xhr.open("PUT", signed_request);
xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.onload = function() {
if (xhr.status === 200) {
done()
};
};
xhr.send(file);
}
function sign_request(file, done) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/sign?file_name=" + file.name + "&file_type=" + file.type);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
done(response);
}
};
xhr.send();
};
document.getElementById("image").onchange = function() {
var file = document.getElementById("image").files[0]
if (!file) return
sign_request(file, function(response) {
upload(file, response.signed_request, response.url, function() {
document.getElementById("preview").src = response.url
});
});
};
</script>
route:
var aws = require('aws-sdk');
appRoutes.get('/sign', function(req, res){
aws.config.update({accessKeyId: config.awsAccessKeyId, secretAccessKey: config.awsSecretAccessKey});
var s3 = new aws.S3();
var options = {
Bucket: config.awsBucket,
Key: req.query.file_name,
Expires: 60,
ContentType: req.query.file_type,
ACL: 'public-read'
}
s3.getSignedUrl('putObject', options, function(err, data){
if(err) return res.send('Error with S3')
res.json({
signed_request: data,
url: 'https://s3.amazonaws.com/' + config.awsBucket + '/' + req.query.file_name
});
});
});
The issue was unrelated to the code and an issue with the permissions provided to the user with the auth key. After giving the user an AdministrativeAccess policy the issue was resolved.

Resources