Skip to content

Commit d2aceb2

Browse files
committed
init
1 parent 3815e76 commit d2aceb2

File tree

11 files changed

+196
-142
lines changed

11 files changed

+196
-142
lines changed

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"workbench.colorTheme": "Abyss"
3+
}

README.md

+58-20
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,72 @@
1-
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
1+
# Next.js PDF Parser Template 📄🔍
22

3-
## Getting Started
3+
## Introduction
44

5-
First, run the development server:
5+
I was having some trouble parsing PDFs in Next.js. I hope this template saves you some time and trouble. It's a basic `create-next-app` with PDF parsing implemented using the [pdf2json library](https://github.com/modesty/pdf2json) and file uploading facilitated by [FilePond](https://github.com/pqina/react-filepond).
66

7-
```bash
8-
npm run dev
9-
# or
10-
yarn dev
11-
# or
12-
pnpm dev
7+
## Installation & Setup 🚀
8+
9+
1. **Clone the repository**:
10+
2. `git clone [repository-url]`
11+
3. **Navigate to the project directory**:
12+
4. `cd nextjs-pdf-parser`
13+
5. **Install dependencies**:
14+
6. ```bash
15+
npm install
16+
# or
17+
yarn install
18+
```
19+
7. **Run the development server**:
20+
21+
```bash
22+
npm run dev
23+
# or
24+
yarn dev
25+
```
26+
27+
Visit `http://localhost:3000` to view the application.
28+
29+
## Usage 🖱
30+
31+
Navigate to `http://localhost:3000` and use the FilePond uploader to select and upload a PDF. Once uploaded, the content of the PDF is parsed and printed to the server console (Note: it will not be printed to the browser log).
32+
33+
## Technical Details 🛠
34+
35+
- **nodeUtil is not defined Error**:
36+
37+
To bypass the `nodeUtil is not defined` error, the following configuration was added to `next.config.js`:
38+
39+
```javascript
40+
const nextConfig = {
41+
experimental: {
42+
serverComponentsExternalPackages: ['pdf2json'],
43+
},
44+
};
45+
46+
module.exports = nextConfig;
1347
```
1448

15-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
49+
See more details [here](https://github.com/modesty/pdf2json/issues/303)
50+
51+
- **Blank output from `pdfParser.getRawTextContent()`**:
52+
53+
This issue might be due to incorrect type definitions. There are two potential solutions:
1654
17-
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
55+
1. **Fix TypeScript definitions**: Update the type definition for PDFParser.
1856
19-
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
57+
2. **Bypass type checking**: Instantiate PDFParser as shown:
2058
21-
## Learn More
59+
`const pdfParser = new (PDFParser as any)(null, 1);`
2260
23-
To learn more about Next.js, take a look at the following resources:
61+
For more details, refer to my comment on [this GitHub issue](https://github.com/modesty/pdf2json/issues/273#issuecomment-1662587255).
2462
25-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
63+
## Acknowledgements 🙏
2764
28-
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
65+
A special thanks to the following libraries and their contributors:
2966
30-
## Deploy on Vercel
67+
- **[FilePond](https://pqina.nl/filepond/)**: For providing a seamless and user-friendly file uploading experience.
68+
- **[pdf2json](https://www.npmjs.com/package/pdf2json)**: For its efficient and robust PDF parsing capabilities.
3169
32-
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
70+
## License 📜
3371
34-
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
72+
MIT License

app/api/upload/route.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { NextRequest, NextResponse } from 'next/server'; // To handle the request and response
2+
import { promises as fs } from 'fs'; // To save the file temporarily
3+
import { v4 as uuidv4 } from 'uuid'; // To generate a unique filename
4+
import PDFParser from 'pdf2json'; // To parse the pdf
5+
6+
export async function POST(req: NextRequest) {
7+
const formData: FormData = await req.formData();
8+
const uploadedFiles = formData.getAll('filepond');
9+
let fileName = '';
10+
let parsedText = '';
11+
12+
if (uploadedFiles && uploadedFiles.length > 0) {
13+
const uploadedFile = uploadedFiles[1];
14+
console.log('Uploaded file:', uploadedFile);
15+
16+
// Check if uploadedFile is of type File
17+
if (uploadedFile instanceof File) {
18+
// Generate a unique filename
19+
fileName = uuidv4();
20+
21+
// Convert the uploaded file into a temporary file
22+
const tempFilePath = `/tmp/${fileName}.pdf`;
23+
24+
// Convert ArrayBuffer to Buffer
25+
const fileBuffer = Buffer.from(await uploadedFile.arrayBuffer());
26+
27+
// Save the buffer as a file
28+
await fs.writeFile(tempFilePath, fileBuffer);
29+
30+
// Parse the pdf using pdf2json. See pdf2json docs for more info.
31+
32+
// The reason I am bypassing type checks is because
33+
// the default type definitions for pdf2json in the npm install
34+
// do not allow for any constructor arguments.
35+
// You can either modify the type definitions or bypass the type checks.
36+
// I chose to bypass the type checks.
37+
const pdfParser = new (PDFParser as any)(null, 1);
38+
39+
// See pdf2json docs for more info on how the below works.
40+
pdfParser.on('pdfParser_dataError', (errData: any) =>
41+
console.log(errData.parserError)
42+
);
43+
44+
pdfParser.on('pdfParser_dataReady', () => {
45+
console.log((pdfParser as any).getRawTextContent());
46+
parsedText = (pdfParser as any).getRawTextContent();
47+
});
48+
49+
pdfParser.loadPDF(tempFilePath);
50+
} else {
51+
console.log('Uploaded file is not in the expected format.');
52+
}
53+
} else {
54+
console.log('No files found.');
55+
}
56+
57+
const response = new NextResponse(parsedText);
58+
response.headers.set('FileName', fileName);
59+
return response;
60+
}

app/layout.tsx

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
import './globals.css'
2-
import type { Metadata } from 'next'
3-
import { Inter } from 'next/font/google'
1+
import './globals.css';
2+
import type { Metadata } from 'next';
3+
import { Inter } from 'next/font/google';
44

5-
const inter = Inter({ subsets: ['latin'] })
5+
const inter = Inter({ subsets: ['latin'] });
66

77
export const metadata: Metadata = {
8-
title: 'Create Next App',
9-
description: 'Generated by create next app',
10-
}
8+
title: 'Next.js PDF Parser',
9+
description: 'Created by tuffstuff9 // github.com/tuffstuff9',
10+
};
1111

1212
export default function RootLayout({
1313
children,
1414
}: {
15-
children: React.ReactNode
15+
children: React.ReactNode;
1616
}) {
1717
return (
18-
<html lang="en">
18+
<html lang='en'>
1919
<body className={inter.className}>{children}</body>
2020
</html>
21-
)
21+
);
2222
}

app/page.tsx

+5-107
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,11 @@
1-
import Image from 'next/image'
1+
import FileUpload from '@/components/file-upload';
22

33
export default function Home() {
44
return (
5-
<main className="flex min-h-screen flex-col items-center justify-between p-24">
6-
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
7-
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
8-
Get started by editing&nbsp;
9-
<code className="font-mono font-bold">app/page.tsx</code>
10-
</p>
11-
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
12-
<a
13-
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
14-
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
15-
target="_blank"
16-
rel="noopener noreferrer"
17-
>
18-
By{' '}
19-
<Image
20-
src="/vercel.svg"
21-
alt="Vercel Logo"
22-
className="dark:invert"
23-
width={100}
24-
height={24}
25-
priority
26-
/>
27-
</a>
28-
</div>
29-
</div>
30-
31-
<div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 before:lg:h-[360px] z-[-1]">
32-
<Image
33-
className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
34-
src="/next.svg"
35-
alt="Next.js Logo"
36-
width={180}
37-
height={37}
38-
priority
39-
/>
40-
</div>
41-
42-
<div className="mb-32 grid text-center lg:mb-0 lg:grid-cols-4 lg:text-left">
43-
<a
44-
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
45-
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
46-
target="_blank"
47-
rel="noopener noreferrer"
48-
>
49-
<h2 className={`mb-3 text-2xl font-semibold`}>
50-
Docs{' '}
51-
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
52-
-&gt;
53-
</span>
54-
</h2>
55-
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
56-
Find in-depth information about Next.js features and API.
57-
</p>
58-
</a>
59-
60-
<a
61-
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
62-
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
63-
target="_blank"
64-
rel="noopener noreferrer"
65-
>
66-
<h2 className={`mb-3 text-2xl font-semibold`}>
67-
Learn{' '}
68-
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
69-
-&gt;
70-
</span>
71-
</h2>
72-
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
73-
Learn about Next.js in an interactive course with&nbsp;quizzes!
74-
</p>
75-
</a>
76-
77-
<a
78-
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
79-
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
80-
target="_blank"
81-
rel="noopener noreferrer"
82-
>
83-
<h2 className={`mb-3 text-2xl font-semibold`}>
84-
Templates{' '}
85-
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
86-
-&gt;
87-
</span>
88-
</h2>
89-
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
90-
Explore the Next.js 13 playground.
91-
</p>
92-
</a>
93-
94-
<a
95-
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
96-
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
97-
target="_blank"
98-
rel="noopener noreferrer"
99-
>
100-
<h2 className={`mb-3 text-2xl font-semibold`}>
101-
Deploy{' '}
102-
<span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
103-
-&gt;
104-
</span>
105-
</h2>
106-
<p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
107-
Instantly deploy your Next.js site to a shareable URL with Vercel.
108-
</p>
109-
</a>
5+
<main className='flex min-h-screen flex-col items-center justify-between p-24'>
6+
<div className='w-96'>
7+
<FileUpload />
1108
</div>
1119
</main>
112-
)
10+
);
11311
}

components/file-upload.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use client';
2+
import { FilePond } from 'react-filepond';
3+
import 'filepond/dist/filepond.min.css';
4+
import { useState } from 'react';
5+
6+
export default function FileUpload() {
7+
return (
8+
<FilePond
9+
server={{
10+
process: '/api/upload',
11+
fetch: null,
12+
revert: null,
13+
}}
14+
/>
15+
);
16+
}

next.config.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
/** @type {import('next').NextConfig} */
2-
const nextConfig = {}
2+
const nextConfig = {
3+
experimental: {
4+
serverComponentsExternalPackages: ['pdf2json'],
5+
},
6+
};
37

4-
module.exports = nextConfig
8+
module.exports = nextConfig;

package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@
1212
"@types/node": "20.4.5",
1313
"@types/react": "18.2.18",
1414
"@types/react-dom": "18.2.7",
15+
"@types/uuid": "^9.0.2",
1516
"autoprefixer": "10.4.14",
17+
"filepond": "^4.30.4",
1618
"next": "13.4.12",
19+
"pdf2json": "^3.0.4",
1720
"postcss": "8.4.27",
1821
"react": "18.2.0",
1922
"react-dom": "18.2.0",
23+
"react-filepond": "^7.1.2",
2024
"tailwindcss": "3.3.3",
21-
"typescript": "5.1.6"
25+
"typescript": "5.1.6",
26+
"uuid": "^9.0.0"
2227
}
2328
}

public/next.svg

-1
This file was deleted.

public/vercel.svg

-1
This file was deleted.

0 commit comments

Comments
 (0)