sei-ec-remote / project-4-issues

Open an issue to receive help on project 4
0 stars 0 forks source link

Uploading file to S3 bucket #135

Closed bostonbachexchange closed 1 year ago

bostonbachexchange commented 2 years ago

What stack are you using?

MERN

What's the problem you're trying to solve?

Trying to get file object to be send and stored in s3 bucket on submit.

Post any code you think might be relevant (one fenced block per file)

s3 from API

require('dotenv').config()
//var fs = require('fs');
const AWS = require ('aws-sdk')
// Create S3 service object
const s3 = new AWS.S3({apiVersion: '2006-03-01'})

// Read the file elsewhere, accept it here
module.exports = function (file) {
    console.log(file.mimetype)
    const uploadParams = {
        Bucket: process.env.BUCKET, 
        Key: Date.now() + '_' + file.originalname, 
        Body: file.buffer,
        ACL: 'public-read',
        ContentType: file.mimetype
    }

    return s3.upload(uploadParams).promise()
}

Form from client `import { Form, Button, Spinner } from 'react-bootstrap' import { useState } from 'react' import axios from 'axios' import apiUrl from './../apiConfig'

const HomeTwo = ({ msgAlert }) => { const [ selected, setSelected ] = useState(null) const [ upload, setUpload ] = useState({}) const [ loading, setLoading ] = useState(null)

const handleChange = (e) => {
    e.preventDefault()
    setSelected(e.target.files[0])
}

const handleSubmit =(e) => {
    e.preventDefault()
    setLoading(true)
    const data = new FormData()
    data.append('upload', selected)
    axios({
        url: `${apiUrl}/uploads`,
        method: 'POST',
        //short for data: data
        data
    })
        .then(res => {
            setUpload(res.data.upload)
            msgAlert('Image upload success', 'success')
        })
        .then(() => setLoading(false))
        .catch(err => {
            msgAlert('Error uploading image', 'error')
        })
}
return (
    <>

        <h2>Home Page</h2>
        {upload.url ? ( <img className={'display-image'} alt={upload.url} src={upload.url}/> ) : '' }
        {loading ? (<Spinner animation="border" />) : ''}
        {/* form for file input */}
        <Form onSubmit={handleSubmit}>
        <Form.Group className="mb-3">
            <Form.Label>Default file input example</Form.Label>
            <Form.Control type="file" onChange={handleChange} />
        </Form.Group>
        <Button type="submit" variant="outline-secondary">Secondary</Button>
        </Form>
    </>
)

}`

If you see an error message, post it here. If you don't, what unexpected behavior are you seeing?

Error: Cannot find module '../models/upload' Require stack:

Screen Shot 2022-08-26 at 9 12 42 AM

What is your best guess as to the source of the problem?

Problem with user model?

What things have you already tried to solve the problem?

npm install multer npm intsall aws-sdk created aws account Set up s3 bucket with IAM

Paste a link to your repository here https://github.com/bostonbachexchange/project_4_API https://github.com/bostonbachexchange/project_4_Client

timmshinbone commented 2 years ago

Looks like it's having trouble finding your upload routes in server.js, maybe check your path for the import?

bostonbachexchange commented 2 years ago

I made a few changes to Upload and upload model.... (not how I want to set it up overall, just trying to get it to work.) I'm getting an error now about credentials. I have them set up in the .env, but i'm not sure how to send it to s3

`require('dotenv').config() //var fs = require('fs'); const AWS = require ('aws-sdk') // Create S3 service object const s3 = new AWS.S3({apiVersion: '2006-03-01'})

//

// const bucketName = process.env.AWS_BUCKET_NAME const region = process.env.AWS_ACCESS_KEY const accessKeyId = process.env.AWS_ACCESS_KEY const secretAccessKey = process.env.AWS_SECRET_KEY

// Read the file elsewhere, accept it here module.exports = function (file) { console.log(file.mimetype) const uploadParams = { Bucket: process.env.BUCKET, // accessKeyId:process.env.AWS_ACCESS_ID, // secretAccessKey: process.env.AWS_SECRET_KEY, // accessKeyId: process.env.AWS_ACCESSKEY , Key: Date.now() + '' + file.originalname, Body: file.buffer, ACL: 'public-read', ContentType: file.mimetype, }

return s3.upload(uploadParams).promise()

}`

Screen Shot 2022-08-26 at 9 47 24 AM
mattkeane-ga commented 2 years ago

Hard to read what's going on in your code here. Can you format it in a code block please?

bostonbachexchange commented 2 years ago

its on github

https://github.com/bostonbachexchange/project_4_API

bostonbachexchange commented 2 years ago

for some reason when I submit the code it takes out the alignment, I thought I had it in the code block though

`require('dotenv').config() //var fs = require('fs'); const AWS = require ('aws-sdk') // Create S3 service object const s3 = new AWS.S3({apiVersion: '2006-03-01'})

//

// const bucketName = process.env.AWS_BUCKET_NAME const region = process.env.AWS_ACCESS_KEY const accessKeyId = process.env.AWS_ACCESS_KEY const secretAccessKey = process.env.AWS_SECRET_KEY

// Read the file elsewhere, accept it here module.exports = function (file) { console.log(file.mimetype) const uploadParams = { Bucket: process.env.BUCKET, // accessKeyId:process.env.AWS_ACCESS_ID, // secretAccessKey: process.env.AWS_SECRET_KEY, // accessKeyId: process.env.AWS_ACCESSKEY , Key: Date.now() + '' + file.originalname, Body: file.buffer, ACL: 'public-read', ContentType: file.mimetype, }

return s3.upload(uploadParams).promise()

}`

bostonbachexchange commented 2 years ago

Screen Shot 2022-08-26 at 11 14 29 AM

mattkeane-ga commented 2 years ago

It looks like you're getting your access key and your secret access key from your environment variables, but then you aren't doing anything with them.

bostonbachexchange commented 2 years ago

exactly

mattkeane-ga commented 2 years ago

So where are you setting your credentials?

bostonbachexchange commented 2 years ago

.env:

AWS_BUCKET_NAME="harmony-haven" AWS_BUCKET_REGION="us-east-1" AWS_ACCESS_KEY="" AWS_SECRET_KEY=""

BUCKET="harmony-haven"

I am still trying to rap my head around S3, but I know I set up IAM policy in AWS that requires permission The keys are there but I redacted them to protect the innocent

mattkeane-ga commented 2 years ago

I'm assuming that you do have AWS_ACCESS_KEY and AWS_SECRET_KEY but have removed them for security (which is the right thing to do), right?

bostonbachexchange commented 2 years ago

right, I just yeeted them out of there before posting

mattkeane-ga commented 2 years ago

My suspicion is that the SDK supports getting the credential information directly from the environment variables, but it doesn't work with an .env file. My suggestion is to try using a shared credentials file in development, and then setting the credentials as environment variables in production. Note that this goes in your home directory and not inside of your project.

bostonbachexchange commented 2 years ago

ok, it might take me some time after lunch to set that up. If I deploy first, I'm guess wondering it it matters if I have that set up?

mattkeane-ga commented 2 years ago

You will probably want it locally for testing. It shouldn't take long to set up.

bostonbachexchange commented 2 years ago

is the shared credentials file a js file? Could I make it like this:

touch .aws\credentials.js

That would be send from in home directory: /Users/jacobclapper

mattkeane-ga commented 2 years ago

It is not javascript, and the file does not have an extension. It should simply be at ~/.aws/credentials.

bostonbachexchange commented 2 years ago

I tried changing the 'aws_secret_access_key' and the secret key to lower case, that seemed to do something. I know have a png file inside of my s3 bucked, but I don't have a key id inside of my uploads folder. I can return a url with {upload.url} on the client side, but instead of a image, it gives me a url string and an error that says 403 forbidden

mattkeane-ga commented 2 years ago

is this in the .env or in the credentials file?

That error sounds like it's more likely bad or missing credentials.

bostonbachexchange commented 2 years ago

.env

mattkeane-ga commented 2 years ago

Try it with the ~/.aws/credentials file instead. Also double check to make sure your key and secret key are correct.

bostonbachexchange commented 2 years ago

im still not sure how to set up .aws/credentials

mattkeane-ga commented 2 years ago

In your home directory, create a directory named .aws. Inside of that, create a file named credentials. Follow the instructions in the documentation on how to add your credentials to that file. Note, this is an ordinary text file. It is not JavaScript.

bostonbachexchange commented 2 years ago

I think I am going to give up on this, I am just chasing error after error without understanding whats going on. Its not a productive use of time. I'v been trying to do this file upload feature for multiple days

mattkeane-ga commented 2 years ago

Did you try the above?