Skip to main content

Overview

Resume Generator accepts resume files in PDF and DOCX formats. The system uses intelligent file type detection based on magic bytes and supports both text-based and scanned documents through AI-powered parsing.

Supported File Formats

The application supports two primary resume formats:
  • PDF (.pdf) - Portable Document Format files
  • DOCX (.docx) - Microsoft Word Open XML documents
The system uses magic byte detection to identify file types, which is more reliable than relying on file extensions or MIME types, especially on Windows systems.

File Size Limits

Resume files are subject to the following constraints:
  • Maximum file size: 5MB
  • Storage: Files are processed in memory (not stored on disk)
Files larger than 5MB will be rejected. Compress large files or optimize your resume before uploading.

How File Upload Works

1

File Selection

Select your resume file (PDF or DOCX) from your local system. The file is attached to the resume field in the multipart form data.
2

File Type Detection

The server performs magic byte detection to identify the file type:
  • PDF Detection: Checks for %PDF signature (bytes 0x25 0x50 0x44 0x46)
  • DOCX Detection: Checks for ZIP signature PK.. (bytes 0x50 0x4b 0x03 0x04)
This happens in interview.controller.js:45-47:
const isPdfMagic = b.length >= 4 && b[0] === 0x25 && 
                   b[1] === 0x50 && b[2] === 0x44 && b[3] === 0x46
const isZipMagic = b.length >= 4 && b[0] === 0x50 && 
                   b[1] === 0x4b && b[2] === 0x03 && b[3] === 0x04
3

Text Extraction

The system attempts to extract text from the uploaded file:
  • PDF files: Parsed using pdf-parse library
  • DOCX files: Parsed using mammoth library for raw text extraction
See interview.controller.js:56-66 for implementation details.
4

Fallback to AI Parsing

If local text extraction fails (scanned PDFs, encrypted files, or corrupted documents), the system falls back to AI-powered parsing:
  • File is encoded as base64
  • Sent directly to Google Gemini AI for content extraction
  • This allows processing of image-based or scanned resumes
Implementation in interview.controller.js:69-82.

Upload via API

Resumes are uploaded using multipart/form-data encoding. Here’s the complete request structure:

Request Format

POST /api/interview/
Content-Type: multipart/form-data
Cookie: connect.sid=<session-cookie>

--boundary
Content-Disposition: form-data; name="resume"; filename="my-resume.pdf"
Content-Type: application/pdf

<binary file data>
--boundary
Content-Disposition: form-data; name="jobDescription"

Senior Software Engineer position...
--boundary
Content-Disposition: form-data; name="selfDescription"

5 years of experience in full-stack development...
--boundary
Content-Disposition: form-data; name="title"

Senior Software Engineer
--boundary--

JavaScript Example

const formData = new FormData()

// Required fields
formData.append("jobDescription", "Senior Software Engineer...")

// Optional but recommended
formData.append("resume", resumeFile) // File object
formData.append("selfDescription", "5 years of experience...")
formData.append("title", "Senior Software Engineer")

const response = await fetch("http://localhost:3000/api/interview/", {
  method: "POST",
  body: formData,
  credentials: "include",
  headers: {
    "Content-Type": "multipart/form-data"
  }
})
From interview.api.js:12-32.

cURL Example

curl -X POST http://localhost:3000/api/interview/ \
  -H "Content-Type: multipart/form-data" \
  -F "resume=@/path/to/resume.pdf" \
  -F "jobDescription=Senior Software Engineer position..." \
  -F "selfDescription=5 years of experience..." \
  -F "title=Senior Software Engineer" \
  --cookie "connect.sid=your-session-cookie"

File Processing Logic

The middleware and controller work together to process uploaded files:

Middleware Configuration

Configured in file.middleware.js:4-9:
const upload = multer({
    storage: multer.memoryStorage(),
    limits: {
        fileSize: 5 * 1024 * 1024 // 5MB
    }
})

Controller Processing

The upload is handled by a single middleware function:
upload.single("resume")
This is configured in interview.routes.js:15.

Error Handling

Common Errors

ErrorStatus CodeCause
”Job description is required”400Missing jobDescription field
”Either a resume file or ‘selfDescription’ is required”400No resume uploaded and no self-description provided
”Unsupported resume file type”400File is neither PDF nor DOCX
”Unable to read the uploaded resume”400Local parsing failed and no fallback available
”Could not extract text from the resume file”400No text extracted and no alternative input provided

Validation Logic

From interview.controller.js:16-29:
if (!resolvedJobDescription) {
    return res.status(400).json({
        message: "Job description is required (send as 'jobDescription')."
    })
}

if (!req.file && !resolvedSelfDescription) {
    return res.status(400).json({
        message: "Either a resume file (field 'resume') or 'selfDescription' is required."
    })
}
If you don’t have a resume file, you can provide a detailed selfDescription instead. The system accepts either one or both.

Best Practices

Text-based PDFs parse faster and more accurately than scanned images. Use tools like Adobe Acrobat or Word to export text-based PDFs.
Keep resume files under 2MB for faster upload and processing. Remove unnecessary images or compress the PDF.
While only one is required, providing both gives the AI more context to generate better interview reports:
  • Resume: Structured work history and skills
  • Self-description: Additional context, soft skills, and personal narrative
Stick to standard fonts (Arial, Times New Roman, Calibri) for better text extraction accuracy.

Next Steps

Generate Interview Reports

Learn how to generate comprehensive interview reports using your uploaded resume

API Reference

View the complete API documentation for the interview generation endpoint

Build docs developers (and LLMs) love