Ruffyg
Ruffyg

Reputation: 103

Next.js Typescript PrimeReact FileUpload preparation

right now I'm working with Next.js and Typescript in a little project of mine. For doing a FileUpload I'm using PrimeReact and the module FileUpload.

To make it work, I searched for a tutorial and found this on stackoverflow:

Link to stackoverflow code

This would be perfect, but sadly it is described in javascript. So i tryed to code in Next.js and Typescript. And it looked like this:

import "./page.css";

import { Document } from "@/components/Document";
import { FileUpload, FileUploadHandlerEvent } from 'primereact/fileupload'; // Ensure you import FileUploadHandlerEvent

export const dynamic = 'force-dynamic';

export default function Extras() {
  let breadcrumb = [{label: "Extras"}];

  const invoiceUploadHandler = async (event: FileUploadHandlerEvent) => {
    "use server"
    const { files } = event;
    const [file] = files;
    
    const fileReader = new FileReader();
    fileReader.onload = (e: any) => {
        uploadInvoice(e.target.result);
    };
    fileReader.readAsDataURL(file);
  };

  const uploadInvoice = async (invoiceFile: File) => {
    let formData = new FormData();
    formData.append('invoiceFile', invoiceFile);
    console.log("Hallo")

    await fetch(`https://httpbin.org/anything`, {
      method: 'POST',
      body: formData
    });
  };

  return (
    <>
      <Document title="Extras" breadcrumb={breadcrumb}/>
      <FileUpload mode="basic" name="demo" url="/api/upload" accept="image/*" maxFileSize={1000000} auto chooseLabel="Browse" />
      <FileUpload mode="basic" name="demo" accept="image/*" uploadHandler={invoiceUploadHandler} maxFileSize={1000000} auto chooseLabel="Browse" />
    </>
  );
}

I added two FileUploads to test different approaches. The second one is like the javascript tutorial. And calls the functions in the same page. Sadly it doesn't work because of "use server". Every code under it doesn't work, but I have to add "use server" or I get errors.

Couldn't test this code because of "use server", but this would be my approach.

Now lets talk about the first FileUpload. Instead of calling the uploadHandler, it is sending a request to my Next.js API /api/upload.

This works fine, but instead of receving data in demo of my req.body, my req.body is a readable stream.

Here is some code from my API, it was just for testing and I don't think this is any kind of correct:

// app/api/upload/route.ts

import { NextApiRequest, NextApiResponse } from 'next';
import path from 'path';
import fs from 'fs';

async function postData(data: any) {
    const res = await fetch('https://api.example.com/...', {
        method: 'POST', // Specify the method as POST
        headers: {
            'Content-Type': 'application/json', // Specify the content type as JSON
        },
        body: JSON.stringify(data) // Convert the data to a JSON string
    });

    if (!res.ok) {
        // This will activate the closest `error.js` Error Boundary
        throw new Error('Failed to fetch data');
    }

    return res.json();
}


export async function POST(req: NextApiRequest, res: NextApiResponse) {
    try {
        const reader = await req.body.getReader();
        const content = await reader.read();
        const buffer = Buffer.from(content.value); 
        const filePath = path.join(__dirname, 'test.csv');
        fs.writeFileSync(filePath, buffer);
        
        const data = await postData(buffer)

        console.log('File saved at:', filePath);

        return Response.json({ message: 'File uploaded successfully' }, { status: 200 })
    } catch (error) {
        console.error('Error saving file:', error);
        return Response.json({ message: 'Internal Server Error' }, { status: 500 })
    }
}

Instead of images, I normally work with csv (and other kind of files like pdf) thats why I have my upload written for csv. And it kinda works which is funny because I get a csv file in my route.ts directory but doesn't look like the original file, because above the data there is some more Text about ReadableStream and demo. It is hard to explain.

I also tried to post-fetch the Data like in my first approach but don't think this is right too.

Maybe someone can give me a clean tutorial how to send files in Typescript/Next.js with PrimeReact to my Backend (which is in Java by the way).

Upvotes: 0

Views: 193

Answers (0)

Related Questions