ryanto / next-s3-upload

Upload files from your Next.js app to S3
https://next-s3-upload.codingvalue.com/
543 stars 76 forks source link

TypeError: Body is unusable #172

Open hamadodene opened 8 months ago

hamadodene commented 8 months ago

Hello, I'm trying to pass custom parameters with a request, but I'm encountering an error that I don't understand how to handle. I'm using Next.js 13 with /app/api/s3-upload/route.ts.

This is my client-side code:

    const handleFilesUpload = async () => {
        for (let index = 0; index < files.length; index++) {
            const file = files[index];
            const { url } = await uploadToS3(file, {
                endpoint: {
                    request: {
                        body: {
                            courseId: courseId,
                            chatId: chatId
                        }
                    }
                }
            })

            setUrls(current => [...current, url]);
        }
    }

This is my server-side code:

import  { POST as route } from "next-s3-upload/route"

export const POST = route.configure({
    async key(req, filename) {
        const body = await req.json()
        console.log("body " + body )
        return `${filename}`
    },
})

And this is the exception I'm facing:

TypeError: Body is unusable
    at specConsumeBody (node:internal/deps/undici/undici:6630:15)
    at NextRequest.json (node:internal/deps/undici/undici:6533:18)
    at Object.key (webpack-internal:///(rsc)/./app/api/s3-upload/route.ts:9:32)
    at eval (webpack-internal:///(rsc)/./node_modules/next-s3-upload/dist/handler-d792c287.mjs:209:43)
    at u (webpack-internal:///(rsc)/./node_modules/next-s3-upload/dist/handler-d792c287.mjs:134:19)
    at Object.eval [as next] (webpack-internal:///(rsc)/./node_modules/next-s3-upload/dist/handler-d792c287.mjs:83:20)
    at l (webpack-internal:///(rsc)/./node_modules/next-s3-upload/dist/handler-d792c287.mjs:46:21)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
hamadodene commented 8 months ago

usingconst body = req.body, the body is always emty

hamadodene commented 8 months ago

@ryanto can you help me to solve this issue?

ryanto commented 8 months ago

This sounds like a bug, sorry about that! I think the fix should be straight forward, but I'll need to dig into it first.

If you need to get unstuck right now then I'd recommend using the pages api route. Setup the API route under /pages/api/s3-upload. Even if you're using the app router, pages api routes will still work. See here: https://next-s3-upload.codingvalue.com/setup#api-route-(pages-router)

hamadodene commented 8 months ago

Thanks @ryanto ...the workaround work

RobCabrera commented 7 months ago

This sounds like a bug, sorry about that! I think the fix should be straight forward, but I'll need to dig into it first.

If you need to get unstuck right now then I'd recommend using the pages api route. Setup the API route under /pages/api/s3-upload. Even if you're using the app router, pages api routes will still work. See here: https://next-s3-upload.codingvalue.com/setup#api-route-(pages-router)

When adding the /pages API route, is it within the app directory or outside? I tried both ways, and the endpoint cannot be found.

I am trying to pass the following parameter in the body:

   await uploadToS3(file,{
        endpoint: {
            request: {
                url: "/api/dataFiles/s3-upload",
                body: {
                    county: countySelected
                }
            }
        }
    });

Any guidance will be greatly appreciated. thanks!

hamadodene commented 7 months ago

I think the page route is outside the app directory... Before next 13 , pages/api was used instead of app/api

RobCabrera commented 7 months ago

I think the page route is outside the app directory... Before next 13 , pages/api was used instead of app/api

I decided not to use the pages route and do the following to get the parameter I needed. Enough for my project.

/app/api/s3-upload/route.js

import { sanitizeKey } from "next-s3-upload";
import { POST as route } from "next-s3-upload/route";
export const POST = route.configure({
    async key(req, filename){
        const url = req.url.split('?')[1];
        const params = new URLSearchParams(url);
        const countyValue = params.get('myparam');
        return `${myparam}/${sanitizeKey(filename)}`;
    }
})

/fileuploadpage.js

let handleFileChange = async event => {
    let file = event.target.files[0];
    await uploadToS3(file,{
        endpoint: {
            request: {
                url: `/api/s3-upload/?myparam=folderName`
            }
        }
    });
  };
XavierZambrano commented 6 months ago

Generate an unnecessary 308 redirect to /api/s3-upload?myparam=folderName (without the last "/"), so omit the last "/"

From:

            url: `/api/s3-upload/?myparam=folderName`

To:

            url: `/api/s3-upload?myparam=folderName`