skip to Main Content

I was developing nodejs api to upload file to my AWS s3. I followed some online articles and using the code below. The files (images/word/pdf) get successfully uploaded to s3. However they do not open. Or give error when downloading and opening in local. One thing noticed here is that files uploaded through my web app have the metadata content-type:"application/octet-stream" while files uploaded manually to s3 have metadata content-type:"image/jpeg". Am I missing something. Here is my nodejs api:

    app.post("/uploadfile", upload.single("file"), async (req, res) => {
      try {
        console.log(req.file);
        var file = req.file;
    
        const fileStream = fs.createReadStream(file.path);
    
        const params = {
          Bucket: bucketName,
          Key: file.originalname,
          Body: fileStream,
        };
        const result = await s3.upload(params).promise();
        return res.status(200).send({
          ok: true,
          message: "File upload successful",
          location: result.Location,
        });
      } catch (err) {
        res.status(500).send({
          ok: false,
          message: "Failed to upload file. Error: " + err.message,
        });
      }
    });

Front end code:

const [file, setFile] = useState();
  const onSubmit = async (data) => {
    console.log(data);
    const fileData = new FormData();
    fileData.append("file", file);

    const uploadResult = await uploadFile(fileData);
    console.log(uploadResult);
}

const uploadFile = async (data) => {
  const requestOptions = {
    method: "POST",
    body: data,
  };
  const endPoint = DEV_API_URL + "uploadfile";
  const response = await fetch(endPoint, requestOptions);
  const responseJson = await response.json();
  return responseJson;
};

2

Answers


  1. Chosen as BEST ANSWER

    So finally found the solution to my problem. Adding multipart/form-data in my API Gateway settings resolved the issue. Found the solution here


  2. Configure Multer to store files in memory:

    const multer = require('multer');
    
    const upload = multer({
      storage: multer.memoryStorage(),
    });
    

    Now, pass the file buffer directly to the s3. Also, add ContentType to the options:

    app.post("/uploadfile", upload.single("file"), async (req, res) => {
      try {
        console.log(req.file);
        const file = req.file;
    
        const params = {
          Bucket: bucketName,
          Key: file.originalname,
          Body: file.buffer,
          ContentType: file.mimetype
        };
        const result = await s3.upload(params).promise();
        return res.status(200).send({
          ok: true,
          message: "File upload successful",
          location: result.Location,
        });
      } catch (err) {
        res.status(500).send({
          ok: false,
          message: "Failed to upload file. Error: " + err.message,
        });
      }
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search