Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uploading file as buffer does not works in production. #650

Closed
nirvikpurkait opened this issue Jan 31, 2024 · 17 comments
Closed

Uploading file as buffer does not works in production. #650

nirvikpurkait opened this issue Jan 31, 2024 · 17 comments

Comments

@nirvikpurkait
Copy link

nirvikpurkait commented Jan 31, 2024

Describe the bug in a sentence or two.

When uploading a file as an byteArrayBuffer in Next.Js application , if the server is in development, the file gets uploaded, but if the server is in production, it throws error. (Error screenshot is provided below)

Issue Type (Can be multiple)

  • Production (works in development, but not in production)

Steps to reproduce

  • Go to this link.
  • Enter CLOUDINARY_API_COULD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET in a .env file.
  • Run npm run dev , it works (file uploads).
  • Build the application, run npm run build, then launch application, run npm start.
  • Try to to upload a file, (throws error).

Error screenshots

Screenshot 2024-02-01 003806

Versions and Libraries (fill in the version numbers)

Cloudinary_NPM SDK version
Node - v20.9.0 (codesandbox), v20.9.0 (system)
NPM - 9.8.1(codesandbox), 10.2.4 (system)

Config Files (Please paste the following files if possible)

{
  "name": "nextjs",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "cloudinary": "^2.0.0",
    "next": "14.1.0",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "autoprefixer": "^10.4.17",
    "eslint": "^8",
    "eslint-config-next": "14.1.0",
    "postcss": "^8",
    "tailwindcss": "^3.3.0",
    "typescript": "^5"
  }
}

Repository

codesandbox

@skalahasti-cloudinary
Copy link

Hi @nirvikpurkait ,

Thanks for contacting Cloudinary.

The codesandbox you provided works fine without a problem. I looked at the logs of your account and I see that there could be a problem with the API Config in Production. Can you please check the settings accordingly of the API Key and API Secret?

Thanks,
Sree

@nirvikpurkait
Copy link
Author

Hi @skalahasti-cloudinary , thanks for your response.

As you said earlier -

I looked at the logs of your account and I see that there could be a problem with the API Config in Production.

Maybe you looked at the logs, when I accidentally re-run the code, after I changed the .env file, before sharing the codesandbox.

Anyway, I have checked the log also, built and run the app again. It still gives me the error.

I made a video about the error in production, and I wanted to attach the video here, but the video is too large to upload here, so I am providing a link for the video.

In case you can't find the video or don't have time to see through it, (as it is more than 2 min.) I am also going to provide some snapshot of it.

  • Works fine with dev server
    1

  • build the app with same .env
    2

  • Error in production
    3

I reproduced the error with same .env file using in development and production (without changing any value), after the video I changed the .env file again (trying not to share the API SECRET).

@tommyg-cld
Copy link
Contributor

tommyg-cld commented Feb 2, 2024

@nirvikpurkait thx for the reply.

So what we're seeing in the failed uploads is that the API key param contains SVG file data as well instead of it being part of the file parameter e.g.

5xxxxxxxxxxxxx8
--xxxxxxxxxxx
Content-Disposition: form-data; name="file"; filename="file"
Content-Type: application/octet-stream

<svg width="638" height="599" viewBox="0 xxxxxx 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="text">
<path id="The" d="M2xxxxxx36.0...

As you can see, you need to only send 5xxxxxxxxxxxxx8.

Please check why in prod mode your app is including the SVG file data in the API key instead of the file parameter.

@thomaslenaour
Copy link

Hello, I'm facing the exact same issue. Everything works perfectly in development mode, but in production, I encounter the same error.

When I submit a form with files using a Server Action, I encounter an error when trying to upload.

Here's the relevant code:

const folderPrefix = getCloudinaryEnv();
const folder = 'test';
const arrayBuffer = await file.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);

return await new Promise((resolve, reject) => {
  cloudinary.uploader
    .upload_stream(
      { tags, folder: `${folderPrefix}/${folder}` },
      (error, result) => {
        if (error) {
          reject(error);
          return;
        }
        resolve(result);
      },
    )
    .end(buffer);
});

The error :

error {
  message: `Server return invalid JSON response. Status Code 500. SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON`,
  name: 'Error',
  http_code: 500
}

@nirvikpurkait Did you find a solution?


Framework: Next.js 14.1.0
Hosting: Vercel

@thomaslenaour
Copy link

thomaslenaour commented Feb 12, 2024

I just found a potential solution (or instead an alternative) :

I convert files into Base 64 before uploading, and I use the cloudinary.uploader.upload() method.

Here's my code :

import mime from 'mime';

const file = formData.get('image') as File;
const arrayBuffer = await file.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
const base64File = Buffer.from(buffer).toString('base64');
const fileMimeType = mime.getType(file.name);

await cloudinary.uploader.upload(
  `data:${fileMimeType};base64,${base64File}`,
  { tags: ['avatars'], folder: 'images' },
);

Don't forget to do additional checks before uploading (file size, type, etc.).

This code is working for me in production and when I build my project.

Feel free to give me your feedback!


Framework: Next.js 14.1.0
Hosting: Vercel

@tommyg-cld
Copy link
Contributor

@thomaslenaour is it happening when uploading SVG files or any file types?

@thomaslenaour
Copy link

@tommyg-cld In my case it was JPG files. I think this is the same problem for any types, I didn't test other files.

@tommyg-cld
Copy link
Contributor

@thomaslenaour are you able to share a your project via codesandbox or similar so that we can replicate?

@nirvikpurkait
Copy link
Author

@thomaslenaour is it happening when uploading SVG files or any file types?

@tommyg-cld As of now it is happening with all jpg, png, svg file type.

import mime from 'mime';

const file = formData.get('image') as File;
const arrayBuffer = await file.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
const base64File = Buffer.from(buffer).toString('base64');
const fileMimeType = mime.getType(file.name);

await cloudinary.uploader.upload(
`data:${fileMimeType};base64,${base64File}`
{ tags: ['avatars'], folder: 'images' },
);

@thomaslenaour Thanks for sharing the idea, what ever my need is, it can be fulfilled by that.

  • But what if someone needs to upload a stream as written in documentation . In that case it is throwing an error.

@tommyg-cld
Copy link
Contributor

@nirvikpurkait are you able to share your codesandbox project where we can replicate this?

@nirvikpurkait
Copy link
Author

@nirvikpurkait are you able to share your codesandbox project where we can replicate this?

codesandbox

Here you can put your api-key, secret, cloud name, and try it out.

I have also provided some screenshot in this comment

@tommyg-cld
Copy link
Contributor

@nirvikpurkait thanks, i was able to replicate, please leave the sandbox running if you don't mind as we have an internal bug for this and the codesandbox link is really handy.

we will keep you posted.

@Ja3mamtora
Copy link

I just found a potential solution (or instead an alternative) :

I convert files into Base 64 before uploading, and I use the cloudinary.uploader.upload() method.

Here's my code :

import mime from 'mime';

const file = formData.get('image') as File;
const arrayBuffer = await file.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
const base64File = Buffer.from(buffer).toString('base64');
const fileMimeType = mime.getType(file.name);

await cloudinary.uploader.upload(
  `data:${fileMimeType};base64,${base64File}`,
  { tags: ['avatars'], folder: 'images' },
);

Don't forget to do additional checks before uploading (file size, type, etc.).

This code is working for me in production and when I build my project.

Feel free to give me your feedback!

Framework: Next.js 14.1.0 Hosting: Vercel

I want to directly add base64 file to cloudinary any idea about it ?

@tommyg-cld
Copy link
Contributor

@Ja3mamtora can you provide more details on what you're trying to do? The post you are referring does exactly that, are you having issues using it? Note this was a temp workaround suggested by @thomaslenaour until we fix the issue on our end.

@thomaslenaour
Copy link

Hello, I can confirm that the upload_stream() function works great for me in production with the last release v.2.0.3.

Thanks Cloudinary team for the fix!

@tommyg-cld
Copy link
Contributor

@thomaslenaour that is great to hear, thanks for the update. I will be closing this issue then.

@nirvikpurkait
Copy link
Author

Thanks for the fix. Now it is working fine with all jpg, png, svg for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants