Add file upload to your React AI app. Let users upload PDFs and documents, extract text, and ask questions about the content.
Add file upload to your React AI app. Let users upload PDFs and documents, extract text, and ask questions about the content.
Full vector-search RAG is complex. For a React app handling single documents, a simpler approach works well: extract the document text and include it directly in the system prompt. Claude's 200K context window handles surprisingly large documents.
Flow: user uploads file → extract text on the server → store in memory → include as context on every subsequent message.
function FileUpload({ onUpload }) {
const [isDragging, setIsDragging] = useState(false);
const [uploadedFile, setUploadedFile] = useState(null);
async function handleFiles(files) {
const file = files[0];
if (!file) return;
const formData = new FormData();
formData.append('file', file);
try {
const res = await fetch('/api/upload', {
method: 'POST',
body: formData // no Content-Type header — let browser set it
});
const data = await res.json();
setUploadedFile(file.name);
onUpload(data.documentId);
} catch (err) {
console.error(err);
}
}
return (
{ e.preventDefault(); setIsDragging(true); }}
onDragLeave={() => setIsDragging(false)}
onDrop={(e) => { e.preventDefault(); setIsDragging(false); handleFiles(e.dataTransfer.files); }}
>
{uploadedFile
? 📄 {uploadedFile} — ready to chat
: Drop a PDF or text file here, or
}
);
}
npm install multer pdf-parse
const multer = require('multer');
const pdfParse = require('pdf-parse');
const upload = multer({ storage: multer.memoryStorage() });
const documents = new Map(); // in-memory storage (use DB in production)
app.post('/api/upload', upload.single('file'), async (req, res) => {
const file = req.file;
let text = '';
if (file.mimetype === 'application/pdf') {
const data = await pdfParse(file.buffer);
text = data.text;
} else {
text = file.buffer.toString('utf-8');
}
// Truncate to ~100K characters if very large
const truncated = text.slice(0, 100000);
const id = crypto.randomUUID();
documents.set(id, { name: file.originalname, content: truncated });
res.json({ documentId: id, charCount: truncated.length });
});
app.post('/api/chat', async (req, res) => {
const { messages, documentId } = req.body;
let system = 'You are a helpful assistant.';
if (documentId && documents.has(documentId)) {
const doc = documents.get(documentId);
system = `You are a helpful assistant. The user has uploaded a document called "${doc.name}".
Use the following document content to answer their questions:
${doc.content}
Answer questions based on this document. If the answer isn't in the document, say so clearly.`;
}
const response = await client.messages.create({
model: 'claude-3-haiku-20240307',
max_tokens: 1024,
system: system,
messages: messages,
});
res.json({ content: response.content[0].text });
});
Before moving on, confirm understanding of these key concepts: