node-formidable / formidable

The most used, flexible, fast and streaming parser for multipart form data. Supports uploading to serverless environments, AWS S3, Azure, GCP or the filesystem. Used in production.
MIT License
7k stars 680 forks source link

Uploading to s3 using nuxt 3: __dirname is not defined #929

Closed helixion closed 1 year ago

helixion commented 1 year ago

Using the example, but I keep getting the same error. In the example there is no reference to setting __dirname.

I'm using: node v16.16.0 Nuxt 3.2.0 Nitro 2.2.0 Formidable ^2.1.1

My composable:

import formidable, {
  File,
  Files,
  Part,
  Fields,
  Options,
  errors as FormidableErrors,
} from "formidable";
import path from "node:path";
import { PassThrough } from "node:stream";
import AWS from "aws-sdk";
import isUndefined from "lodash/isUndefined";
import { nanoid } from "nanoid";

interface FileUploadOptions
  extends Omit<Options, "filter" | "fileWriteStreamHandler"> {
  dest?: string;
  overwrite?: boolean;
  overWriteFilename?: string;
  bucket: string;
}

const s3Client = new AWS.S3({
  credentials: {

  },
});

const isValidFile = (file: Part) => {
  const types = /jpe?g|png|webp|svg|gif/;
  const ext = types.test(
    path.extname(file.originalFilename as string).toLowerCase()
  );
  const mimetype = types.test(file.mimetype as string);
  if (mimetype && ext) return true;
  return false;
};

export const useFiles = (
  files: any,
  opts: FileUploadOptions
): Promise<{ fields: Fields; files: Files }> => {
  if (isUndefined(opts.bucket)) {
    throw new Error(
      "'opts.bucket' is required. Please input your AWS S3 bucket name."
    );
  }

  const dest = opts?.dest ? opts.dest : "uploads/";
  const overwrite = opts?.dest ? opts.overwrite : false;
  const maxFields = opts.maxFields || 10;
  const maxFiles = opts.maxFiles || 10;
  const maxFileSize = opts.maxFileSize || 120000;
  const maxTotalFileSize = 1 * 1000 * 1000; //1mb total file size.

  let s3Data: AWS.S3.ManagedUpload.SendData[] = [];

  const uploadStream = (file: File) => {
    const pass = new PassThrough();
    s3Client.upload(
      {
        Bucket: opts.bucket,
        Key: file.newFilename,
        Body: pass,
      },
      (err, data) => {
        console.log(err, data);
      }
    );

    return pass;
  };

  const form = formidable({
    fileWriteStreamHandler: uploadStream as any,
    maxFields,
    maxFiles,
    maxFileSize,

    allowEmptyFiles: false,
    filter: isValidFile,
    filename: (name, ext, part) => {
      const _name = !overwrite
        ? dest + nanoid() + ext
        : dest + opts?.overWriteFilename
        ? (opts!.overWriteFilename as string)
        : name + ext;
      return _name;
    },
  });

  return new Promise((resolve, reject) => {
    form.parse(files, (err: typeof FormidableErrors, fields, files) => {
      console.log({ fields, files });
      if (err) reject(err);
      return resolve({ fields, files });
    });
  });
};

my route:

import { useFiles } from "~~/server/services/useFiles";
import authenticatedEventHandler from "~~/server/utils/authenticatedEventHandler";

export default authenticatedEventHandler(null, null, async (event, user) => {
  const identifier = `uploads/${user.username}-${user.id.substring(
    user.id.length,
    user.id.length - 4
  )}`;

  console.log("req", event.node.req);

  try {
    const { files, fields } = await useFiles(event.node.req, {
      bucket: "lobucket",
      dest: identifier,
    });

    console.log({ files, fields });

    return { status: "ok" };
  } catch (err) {
    console.log(err);
    return createError({
      statusCode: 419,
      statusMessage: "Encountered an error.",
    });
  }
});

the error:

ReferenceError: __dirname is not defined                                                                                                                                                                                                                                   10:40:20
    at file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/.nuxt/dev/index.mjs:2470:42
    at Array.forEach (<anonymous>)
    at new IncomingForm (file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/.nuxt/dev/index.mjs:2467:33)
    at formidable (file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/.nuxt/dev/index.mjs:3462:33)
    at useFiles (file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/.nuxt/dev/index.mjs:3532:16)
    at file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/.nuxt/dev/index.mjs:3561:37
    at file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/.nuxt/dev/index.mjs:514:14
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Object.handler (file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/node_modules/h3/dist/index.mjs:990:19)
    at async Server.toNodeHandle (file:///home/<folder>/Projects/workplaces/nuxtApps/nuxt-bko/node_modules/h3/dist/index.mjs:1065:7)
helixion commented 1 year ago

The solution was to use 3.0.