question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Upload File Storage - Nextjs

See original GitHub issue

Bug report

Describe the bug

I’m currently attempting to Upload an Image from my Nextjs Server, and each time I upload the image to Supabase the file size is only 15 bytes (unreadable).

However, when I console log the file in my server, the size shows 181kb.

To Reproduce

Client

    let formData = new FormData();
    formData.append("file", file.file);
    let res = await fetch('/api/product/add, {
      method: "POST",
      body: formData
    });

Backend

      const {data, error} = await supabase.storage.from('my-bucket-name')
        .upload(`my-file-path`, files[0], {
          cacheControl: '3600',
          upsert: false,
          contentType: files[0].type
        })

Middleware for Nextjs Multipart/form-data

export const multipartFormMiddleware = (req, res) => {
  return new Promise((resolve, reject) => {
    const form = new formidable.IncomingForm();
    form.uploadDir = "./";
    form.keepExtensions = true;
    form.parse(req, (err, fields, files) => {
      if (err) {
        const error = new APIError('Multipart Form Error: Server', req.url, 422, req.method);
        error.info = err;
        res.status(422).json({error: error.message, info: error.info })
        return reject(err)
      }

      let parsedFields = {};
      Object.keys(fields).map((key) => {
        parsedFields[key] = JSON.parse(fields[key])
      });

      let parsedFiles = [];
      Object.keys(files).map((key) => {
        parsedFiles.push(files[key]);
      })

      req.body = parsedFields;
      req.files = parsedFiles;

      return resolve(true)
    })
  })
}

My File (Image) - Console log

File {
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  size: 180634,
  path: 'upload_10beef299c6709f0f56bee0e3813f158.jpg',
  name: 'JuanHeadshot copy.jpg',
  type: 'image/jpeg',
  hash: null,
  lastModifiedDate: 2021-11-08T01:44:35.703Z,
  _writeStream: WriteStream {
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: true,
      needDrain: true,
      ending: true,
      ended: true,
      finished: true,
      destroyed: true,
      decodeStrings: true,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: false,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 0,
      prefinished: true,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: true,
      errored: null,
      closed: true
    },
    _events: [Object: null prototype] {},
    _eventsCount: 0,
    _maxListeners: undefined,
    path: 'upload_10beef299c6709f0f56bee0e3813f158.jpg',
    fd: null,
    flags: 'w',
    mode: 438,
    start: undefined,
    autoClose: true,
    pos: undefined,
    bytesWritten: 180634,
    closed: true,
    [Symbol(kFs)]: {
      appendFile: [Function: appendFile],
      appendFileSync: [Function: appendFileSync],
      access: [Function: access],
      accessSync: [Function: accessSync],
      chown: [Function (anonymous)],
      chownSync: [Function (anonymous)],
      chmod: [Function (anonymous)],
      chmodSync: [Function (anonymous)],
      close: [Function: close],
      closeSync: [Function: closeSync],
      copyFile: [Function: copyFile],
      copyFileSync: [Function: copyFileSync],
      createReadStream: [Function: createReadStream],
      createWriteStream: [Function: createWriteStream],
      exists: [Function: exists],
      existsSync: [Function: existsSync],
      fchown: [Function (anonymous)],
      fchownSync: [Function (anonymous)],
      fchmod: [Function (anonymous)],
      fchmodSync: [Function (anonymous)],
      fdatasync: [Function: fdatasync],
      fdatasyncSync: [Function: fdatasyncSync],
      fstat: [Function (anonymous)],
      fstatSync: [Function (anonymous)],
      fsync: [Function: fsync],
      fsyncSync: [Function: fsyncSync],
      ftruncate: [Function: ftruncate],
      ftruncateSync: [Function: ftruncateSync],
      futimes: [Function: futimes],
      futimesSync: [Function: futimesSync],
      lchown: [Function (anonymous)],
      lchownSync: [Function (anonymous)],
      lchmod: [Function (anonymous)],
      lchmodSync: [Function (anonymous)],
      link: [Function: link],
      linkSync: [Function: linkSync],
      lstat: [Function (anonymous)],
      lstatSync: [Function (anonymous)],
      lutimes: [Function: lutimes],
      lutimesSync: [Function: lutimesSync],
      mkdir: [Function: mkdir],
      mkdirSync: [Function: mkdirSync],
      mkdtemp: [Function: mkdtemp],
      mkdtempSync: [Function: mkdtempSync],
      open: [Function: open],
      openSync: [Function: openSync],
      opendir: [Function: opendir],
      opendirSync: [Function: opendirSync],
      readdir: [Function: readdir],
      readdirSync: [Function: readdirSync],
      read: [Function: read],
      readSync: [Function (anonymous)],
      readv: [Function: readv],
      readvSync: [Function: readvSync],
      readFile: [Function: readFile],
      readFileSync: [Function: readFileSync],
      readlink: [Function: readlink],
      readlinkSync: [Function: readlinkSync],
      realpath: [Function],
      realpathSync: [Function],
      rename: [Function: rename],
      renameSync: [Function: renameSync],
      rm: [Function: rm],
      rmSync: [Function: rmSync],
      rmdir: [Function: rmdir],
      rmdirSync: [Function: rmdirSync],
      stat: [Function (anonymous)],
      statSync: [Function (anonymous)],
      symlink: [Function: symlink],
      symlinkSync: [Function: symlinkSync],
      truncate: [Function: truncate],
      truncateSync: [Function: truncateSync],
      unwatchFile: [Function: unwatchFile],
      unlink: [Function: unlink],
      unlinkSync: [Function: unlinkSync],
      utimes: [Function: utimes],
      utimesSync: [Function: utimesSync],
      watch: [Function: watch],
      watchFile: [Function: watchFile],
      writeFile: [Function: writeFile],
      writeFileSync: [Function: writeFileSync],
      write: [Function: write],
      writeSync: [Function: writeSync],
      writev: [Function: writev],
      writevSync: [Function: writevSync],
      Dir: [class Dir],
      Dirent: [class Dirent],
      Stats: [Function: Stats],
      ReadStream: [Getter/Setter],
      WriteStream: [Getter/Setter],
      FileReadStream: [Getter/Setter],
      FileWriteStream: [Getter/Setter],
      _toUnixTimestamp: [Function: toUnixTimestamp],
      F_OK: 0,
      R_OK: 4,
      W_OK: 2,
      X_OK: 1,
      constants: [Object: null prototype],
      promises: [Getter],
      gracefulify: [Function: patch]
    },
    [Symbol(kCapture)]: false,
    [Symbol(kIsPerformingIO)]: false
  },
  [Symbol(kCapture)]: false
}

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

image

System information

  • OS: macOS
  • Browser: Chrome

Additional context

Add any other context about the problem here.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:20 (5 by maintainers)

github_iconTop GitHub Comments

6reactions
dong-qiancommented, Apr 1, 2022

@Phantomat0 Hi, I already slove the issue. Here is an example

import { supabase } from "lib/supabase";
import formidable from "formidable";
import fs from "fs";

async function handler(req, res) {
  const form = new formidable.IncomingForm();
  const uploadFile = async () => {
    // eslint-disable-next-line
    return new Promise((resolve, reject) => {
      form.parse(req, async function (err, fields, files) {
        let filepath = `${fields.id}/${files.file.originalFilename}`;
        filepath = filepath.replace(/\s/g, "-"); // IN CASE YOU NEED TO REPLACE SPACE OF THE IMAGE NAME
        const rawData = fs.readFileSync(files.file.filepath);
        const { error } = await supabase.storage
          .from("property-images")
          .upload(filepath, rawData, {
            contentType: files.file.mimetype,
          });

        if (error || err) {
          return reject({ success: false });
        }
        /** YOU DO NOT NEED BELOW UNLESS YOU WANT TO SAVE PUBLIC URL OF THE IMAGE TO THE DATABASE
        await supabase.from("property-image").insert({
          url: `${process.env.NEXT_PUBLIC_SUPABASE_STORAGE_BASE_URL}/property-images/${filepath}`,
          property_id: fields.id,
        });
       */
        resolve({ success: true });
      });
    });
  };

  try {
    await uploadFile();
    res.status(200).send({ success: true });
  } catch (err) {
    res.status(400).send({ success: false });
  }
}

export const config = {
  api: {
    bodyParser: false,
  },
};

export default handler;
1reaction
Phantomat0commented, Jun 11, 2022

Use the File type from formidable, not from Node. You can tell you’re using the Node File type since “name” doesn’t exist on formidable Files, but rather “originalFilename”. This implies you’re using the @types package from formidable btw.

Import the types as so:

import { Fields, File, Files } from "formidable";
Read more comments on GitHub >

github_iconTop Results From Across the Web

Upload Files to Next.js With API Routes | by Robert S (codeBelt)
A brief overview how to upload files with React and Next.js API Routes. How to use React, Next-Connect, Multer and Axios to upload...
Read more >
How to Implement Drag and Drop File Upload in Next.js
In this tutorial, we will learn how to create a file upload dropzone component in Next.js using the Drag and Drop API's.
Read more >
NextJS: Simple Upload file to server - CodeSandbox
CodeSandbox is an online editor tailored for web applications.
Read more >
How to Upload and Store Files with Vercel
Uploading and storing files from the browser (e.g. images) is a common requirement for applications. If you are using a Headless CMS, it...
Read more >
How to store files in production in Next.js? - Stack Overflow
Next.js does allow file storage at buildtime, but not at runtime. Next.js will not be able to fulfill your file upload requirement.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found