sei-ec-remote / team-project-issues

0 stars 0 forks source link

Unable to upload file #147

Closed rectorjordan94 closed 1 year ago

rectorjordan94 commented 1 year ago

Describe the bug We're using multers3 to upload files to aws, and I am able to upload a file successfully in postman because (when working properly) multer creates a req.file object, which we can then take information from and add it to the req.body so that the route will simultaneously upload to mongoose and aws at the same time. On the frontend however, I cannot seem to get the req.file object to create because I'm having trouble properly passing the file from the form-data.

What is the problem you are trying to solve? Trying to get the html input component to pass the file properly so that multers3 can read it and create a req.file object.

Expected behavior A clear and concise description of what you expected to happen. The file should upload to both the mongodb and our amazon s3 bucket.

What is the actual behavior? A clear and concise description of what actually happened. I've only been able to get the form to pass a File object to axios, which upon axios making the request returns (first console.log is req.body, second is req.file): image This is totally different from the file present that was passed to axios: image

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

axios call:
export const createFile = (user, file) => {
    console.log('file in axios:', file)
    return axios({
        url: `${apiUrl}/files`,
        method: 'POST',
        headers: {
            Authorization: `Token token=${user.token}`
        },
        data: { file }
    })
}

onChange & onSubmit for the new file:
 const onChange = (e) => {
        e.preventDefault()
        console.log(e)
        setSelectedFile(e.target.files[0])
        console.log('file in onChange from newFileModal', selectedFile)
    }

    const onSubmit = (e) => {
        e.preventDefault()
        console.log('selectedFile name in onSubmit', selectedFile)

        createFile(user, selectedFile)

upload file form: 
const UploadFileForm = (props) => {
    const { file, handleChange, handleSubmit } = props

    console.log('file in upload form: ', file)

    return (
        <Container className="justify-content-center">
            <Form onSubmit={handleSubmit}>
                <Form.Group className="m-2">
                    <Form.Label>Choose File:</Form.Label>
                    <Form.Control
                        type='file'
                        name='file'
                        id='file'
                        value={file}
                        onChange={handleChange}
                    />
                </Form.Group>

post route in backend:
router.post('/files', upload.single('file'), requireToken, (req, res, next) => {
    // upload.single() uploads the file to AWS and returns a file object (req.file)

    console.log('body', req.body)
    console.log('file', req.file)   
    req.body.url = req.file.location
    // console.log('body', req.body)
    req.body.owner = req.user._id
    // name field could be key or original name from req.file
    req.body.name = req.file.originalname
    // File type
    req.body.type = req.file.mimetype
    // console.log('body', req.body)
    // console.log('userId', req.user._id)
    req.body.awsKey = req.file.key
    File.create(req.body)
        .then(file => {
            res.status(201).json({ file: file.toObject() })
        })
        .catch(next)
})

What is your best guess as to the source of the problem? I'm guessing that we're handling the data improperly with axios, which is why it isn't getting passed correctly.

What things have you already tried to solve the problem? I've tried using FormData, appending to a formdata object and passing that into axios instead. I've tried trying to send only the path of the file. I've tried adding enctype='multipart/form-data' to the form (which multers3 says it requires) I've tried reconfiguring the axios call with content-type headers. I've tried altering the data in axios (as I'm typing this I tried to change it to data : file and got a new error saying: PayLoadTooLargeError: request entity too large. That's new, and I'm not sure what to do about that either)

Additional context Add any other context about the problem here.

Paste a link to your repository here https://github.com/estebbins/hoistm-client

asands94 commented 1 year ago

Can you send any documentation for what you're using to get this to work?

rectorjordan94 commented 1 year ago

To get this to work, I had to append the file found from e.target.files[0] to a new FormData and then pass that to the axios call function like this: image this also requires the form to have the encType of multipart/form-data (required per multer documentation for upload) In the backend post route, you must pass information created in the req.body to req.file in order to pass aws validations, like this: image Lastly, in server.js you have to alter the express.json and express.urlencoded middlewares to increase the size limit of your req.body like so: image