client icon indicating copy to clipboard operation
client copied to clipboard

Unable to upload image asset (as Blob) from NextJS Route Handler

Open benderillo opened this issue 1 year ago • 13 comments

When trying to upload an image as Blob using the client.assets.upload method inside the Nextjs 13 Route Handler, the method throws error:

Error: Request body must be a string, buffer or stream, got object
    at httpRequester (webpack-internal:///(sc_server)/./node_modules/get-it/dist/index.cjs:468:15)
    at Object.eval (webpack-internal:///(sc_server)/./node_modules/get-it/dist/index.cjs:134:30)
    at Object.publish (webpack-internal:///(sc_server)/./node_modules/get-it/dist/index.cjs:80:28)
    at Observable.eval [as _subscribe] (webpack-internal:///(sc_server)/./node_modules/get-it/dist/middleware.cjs:311:34)
    at Observable._trySubscribe (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:36:25)
    at eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:30:121)
    at Object.errorContext (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/util/errorContext.js:26:9)
    at Observable.subscribe (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:28:24)
    at Observable.eval [as _subscribe] (webpack-internal:///(sc_server)/./node_modules/@sanity/client/dist/index.cjs:815:51)
    at Observable._trySubscribe (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:36:25)
    at eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:30:121)
    at Object.errorContext (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/util/errorContext.js:26:9)
    at Observable.subscribe (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:28:24)
    at eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/operators/filter.js:11:16)
    at OperatorSubscriber.eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/util/lift.js:16:28)
    at eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:30:48)
    at Object.errorContext (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/util/errorContext.js:26:9)
    at Observable.subscribe (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:28:24)
    at eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/operators/map.js:11:16)
    at SafeSubscriber.eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/util/lift.js:16:28)
    at eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:30:48)
    at Object.errorContext (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/util/errorContext.js:26:9)
    at Observable.subscribe (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/Observable.js:28:24)
    at eval (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/lastValueFrom.js:12:16)
    at new Promise (<anonymous>)
    at Object.lastValueFrom (webpack-internal:///(sc_server)/./node_modules/rxjs/dist/cjs/internal/lastValueFrom.js:9:12)
    at AssetsClient.upload (webpack-internal:///(sc_server)/./node_modules/@sanity/client/dist/index.cjs:901:21)

The code is as following:

import { createClient } from '@sanity/client';
const client = createClient({
  projectId: 'sdfsd',
  dataset: 'sdfdsf,
  apiVersion: '2023-02-23',
  useCdn: false,
  token: process.env.SANITY_TOKEN,
});

The route handler file /app/api/myform/route.ts

import { type NextRequest, NextResponse } from 'next/server';
export const dynamic = 'force-dynamic';

export async function POST(req: NextRequest) {
   const form = await req.formData();
   const file = form.get('file') as Blob;

   if (!file) {
      return new NextResponse('Bad request', { status: 400 });
   }

   await client.assets.upload('image', file, { filename: 'image'});
   return NextResponse.json({});
}

I checked that the blob is valid and has the proper image file. I guess the get-it package under the hood always expects Nodejs type of body (not the browser/Web API)

There is a duplicate issue submitted for the same problem on next-sanity repo https://github.com/sanity-io/next-sanity/issues/348

benderillo avatar Feb 24 '23 06:02 benderillo