简体   繁体   中英

How to read files after sending a post request in the req.body

I am running into an issue where when I want to upload an image to s3 bucket nothing goes through.

Basically the only message I get is

API resolved without sending a response for /api/upload/uploadPhoto, this may result in stalled requests.

In the front end, I have an input which can take multiple files ( mainly images ) and then those are stored in event.target.files.

I have a function that stores each file in a state array, and with the button submit it sends a post request to my next.js API.

Here's the logic on the front end:

This function handles the photos, so whenever I add a photo it will automatically add it to the listingPhotos state:

const handleListingPhotos = async (e: any) => {
    setMessage(null);
    let file = e.target.files;

    console.log("hello", file);

    for (let i = 0; i < file.length; i++) {
      const fileType = file[i]["type"];
      const validImageTypes = ["image/jpeg", "image/png"];
      if (validImageTypes.includes(fileType)) {
        setListingPhotos((prev: any) => {
          return [...prev, file[i]];
        });
      } else {
        setMessage("Only images are accepted");
      }
    }
  };

Once the photos are stored in the state, I am able to see the data of the files in the browsers console.log. I run the onSubmit to call the POST API :

const handleSubmit = async (e: any) => {
    e.preventDefault();
    const formData = new FormData();
    formData.append("files[]", listingPhotos);
    await fetch(`/api/upload/uploadPhoto`, {
      method: "POST",
      headers: { "Content-Type": "multipart/form-data" },
      body: formData,
    }).then((res) => res.json());
  };
  console.log("listingphotos:", listingPhotos);

Which then uses this logic to upload to the S3 Bucket, but the issue is that when I log req.body I am getting this type of information:

req.body ------WebKitFormBoundarydsKofVokaJRIbco1
Content-Disposition: form-data; name="files[]"

[object File][object File][object File][object File]
------WebKitFormBoundarydsKofVokaJRIbco1--

api/upload/UploadPhoto logic:

import { NextApiRequest, NextApiResponse } from "next";
const AWS = require("aws-sdk");

const access = {
  accessKeyId: process.env.AWS_ACCESS_KEY_ID as string,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string,
};

// creates an S3 Client
const s3 = new AWS.S3({ region: "region", credentials: access });

export default async function uploadPhoto(
  req: NextApiRequest,
  res: NextApiResponse
) {
  // take info from parent page
  // console.log("req.body: ", req.body);

  if (req.method === "POST") {
    console.log("req.body", req.body);
    let body = req.body;
    let headers = req.headers;
    let contentType = headers["Content-Type"] || headers["content-type"];

    // check for correct content-type
    if (!contentType.startsWith("multipart/form-data")) {
      return { statusCode: 400, body: "Invalid content type" };
    }

    let boundary = contentType.replace("multipart/form-data; boundary=", "");
    let parts = body.split(boundary);

    for (let part of parts) {
      if (part.startsWith("Content-Disposition")) {
        let [fileData] = part.split("\r\n\r\n");
        fileData = fileData.slice(0, -2);
        let [fileName] = part.split("filename=");
        fileName = fileName.slice(1, -1);
        let params = {
          Bucket: "RANDOM BUCKET NAME",
          Key: fileName,
          Body: fileData,
          ContentType: { "image/png": "image/jpg" },
        };
        // Need to set the PARAMS for the upload
        await s3.putObject(params);
        console.log(
          "Successfully uploaded object: " + params.Bucket + "/" + params.Key
        );
      }
    }
    return {
      statusCode: 200,
      body: "File uploaded",
    };
    // Uploads the files to S3
  }
}

I was able to find a way to read if the files were correctly displayed.

req.body {
  fileName: 'b699417375e46286e5a30fc252b9b5eb.png',
  fileType: 'image/png'
}

POST request code was changed to the followng:

const s3Promises = Array.from(listingPhotos).map(async (file) => {
      const signedUrlRes = await fetch(`/api/upload/uploadPhoto`, {
        method: "POST",
        body: JSON.stringify({
          fileName: file.name,
          fileType: file.type,
        }),
        headers: { "Content-Type": "application/json" },
      });

Obviously, this is not the solution but it's part of it. The only problem I am running into right now is handling CORS in order to see if the files are sent to the bucket.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM