How to Upload Files to the server and store in inside the public folder of Nuxt? Not working in production

344 Views Asked by At

I am trying to upload files using an API and then store them inside the public folder of Nuxt.

This code works but is not in production.

~/server/api/upload.post.ts

import path from 'path'
import fs from 'fs'

export default defineEventHandler(async(event) => {
  const files = await readMultipartFormData(event)

  const uploadedFilePaths:string[] = []

  files?.forEach((file) => {
    const filePath = path.join(process.cwd(), 'public', file.filename as string)
    fs.writeFileSync(filePath, file.data)
    uploadedFilePaths.push(`/${file.filename}`)
  })
  return uploadedFilePaths
})

So, I think fs and path from node won't work because the file directory will change in production.

I tried using the useStorage from Nitro but it still doesn't work.

Here is my configuration

nuxt.config.ts

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
  devtools: true,
  nitro: {
    storage: {
      fs: {
        driver: 'fs',
        base: './public'
      }
    },
  }
});

Then the ~/server/api/upload.post.ts

export default defineEventHandler(async (event) => {
  const files = await readMultipartFormData(event)
  const uploadFilePaths:string[] = []
  files?.forEach((file) => {
    useStorage().setItemRaw(`fs:${file.filename}`, file.data)
    uploadFilePaths.push(`${getRequestURL(event).origin}/${file.filename}`)
  }) 
  return uploadFilePaths
});

so when I upload the file in production, it returns the file paths but when I view the uploaded file I get 404 not found.

1

There are 1 best solutions below

2
VonC On

I see:

+----------------------+                +----------------------+
|                      |                |                      |
|   Client Browser     | -- Uploads --> |   Nuxt Server (Dev)  |
|                      |                |                      |
+----------------------+                +----------+-----------+
                                                   |
                                                   | Writes to
                                                   V
                                          +----------------------+
                                          |                      |
                                          |   public/ directory  |
                                          |                      |
                                          +----------------------+

In development, your setup works because the file system paths are consistent and accessible.
However, in production, the file paths and permissions might differ, leading to issues.

As an alternative, you might consider, instead of writing directly to the filesystem, using a more robust solution like cloud storage (e.g., AWS S3, Google Cloud Storage), or a dedicated file storage service. That change will make sure your file uploads work consistently across different environments.

Your upload.post.ts code (using a cloud storage solution (e.g., AWS S3)). You will need to configure the cloud storage SDK with your credentials and bucket details.

import { S3 } from 'aws-sdk';

const s3 = new S3({
  /* Your AWS SDK configuration here */
});

export default defineEventHandler(async (event) => {
  const files = await readMultipartFormData(event)
  const uploadFilePaths:string[] = []

  await Promise.all(files.map(async (file) => {
    const params = {
      Bucket: /* Your Bucket Name */,
      Key: file.filename,
      Body: file.data,
    };

    const uploadResult = await s3.upload(params).promise();
    uploadFilePaths.push(uploadResult.Location);
  }));

  return uploadFilePaths;
});