kampfkuchen
kampfkuchen

Reputation: 484

Uploading file with react hook form

I am trying to upload a PDF file using React Hook Form with next.js in the frontend and node.js in the backend.

The frontend:

const FileUpload = () => {
  const [proof, setProof] = useState({})

  const onSubmit = async (values) => {
    try {
      const proof = values.proof[0]
      let { data } = await axios.post('/api/upload-file', {
        proof,
      })
      setProof(data)
    } catch (err) {
      console.log(err.response)
    }
  }

  <form onSubmit={handleSubmit(onSubmit)} className={styles['form']}>
        <label htmlFor="proof" className={styles['form-input-label']}>
          <input
            type="file"
            name="proof"
            {...register('proof')}
            placeholder=" "
            required
            className={`${
              errors.proof? styles['form-input-error'] : styles['form-input']
            }
                )`}
          />
          <span className={styles['form-input-placeholder']}>
            upload file
          </span>
        </label>
        <p className={styles['form-error']}>{errors.file?.message}</p>
        <button
          type="submit"
          className="btn"
          disabled={!isDirty || !isValid || loading}
        >
          {loading ? <LoadingOutlined spin /> : 'Upload File'}
        </button>
      </form>
    </>
  )
}

export default FileUpload

The backend (/api/upload-file):

export const uploadFile = async (req, res) => {
  try {
    console.log(req.body) // => returns empty object (proof:({}))
    const { proof } = req.body
    if (!proof) return res.status(400).send('File missing')

    // prepare the file
    const base64Data = new Buffer.from(
      proof.replace(/^data:proof\/\w+;base64,/, ''),
      'base64'
    )

    const type = proof.split(';')[0].split('/')[1]

    // image bucket params
    const params = {
      Bucket: 's3-bucket',
      Key: `${nanoid()}.${type}`,
      Body: base64Data,
      ACL: 'public-read',
      ContentType: 'application/pdf',
    }

    // upload to s3
    s3.upload(params, (err, data) => {
      if (err) {
        console.log(err)
        res.sendStatus(400)
      }
      res.send(data)
    })
  } catch (err) {
    console.log(err)
    return res
      .status(400)
      .send(
        'An Error occured'
      )
  }
}

I am not able to pass the file to the backend, all I get is an empty object. I tried researching the axios docs, as well as the react hook form docs, to no avail.

What am I doing wrong?

Thank you for your help!!

Upvotes: 2

Views: 2530

Answers (2)

Teymur Zeynalov
Teymur Zeynalov

Reputation: 1

I think firstly you should test your api, using postman or swagger, try to upload a file if it is works, and redefine your onsubmit. Here you are actually passing an empty object in the moment it is empty

  const proof = values.proof[0]
  let { data } = await axios.post('/api/upload-file', {
    proof,
  })
  setProof(data)

take a look at your backend service responsible for a file uploading , you can use multer or fileinterceptors

Upvotes: 0

Caleb Stephens
Caleb Stephens

Reputation: 11

you have to set the content type to multi-part/formdata and create a formData object to send file content to the backend. You also have to parse that file multi-part/formdata on the backend. Look up Multer for the backend and formData object for frontend.

Upvotes: 1

Related Questions