Full-Stack Project Development

Build a complete full-stack application from scratch including frontend, backend, database, authentication, and deployment.

advanced Backend Development 10 hours

Chapter 8: File Upload and Storage

Chapter 8 of 15

Chapter 8: File Upload and Storage

8.1 File Handling

File uploads require proper handling on both frontend and backend for security and performance.

// Backend - Multer for file uploads
const multer = require('multer');
const path = require('path');

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'uploads/');
    },
    filename: (req, file, cb) => {
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
    }
});

const upload = multer({
    storage: storage,
    limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
    fileFilter: (req, file, cb) => {
        const allowedTypes = /jpeg|jpg|png|gif/;
        const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
        const mimetype = allowedTypes.test(file.mimetype);
        
        if (mimetype && extname) {
            return cb(null, true);
        }
        cb(new Error('Invalid file type'));
    }
});

app.post('/api/upload', upload.single('image'), (req, res) => {
    res.json({ file: req.file.filename });
});

8.2 Frontend File Upload

// React file upload component
function FileUpload({ onUpload }) {
    const [file, setFile] = useState(null);
    const [uploading, setUploading] = useState(false);
    
    const handleFileChange = (e) => {
        setFile(e.target.files[0]);
    };
    
    const handleUpload = async () => {
        if (!file) return;
        
        const formData = new FormData();
        formData.append('image', file);
        
        setUploading(true);
        try {
            const response = await api.post('/api/upload', formData, {
                headers: { 'Content-Type': 'multipart/form-data' }
            });
            onUpload(response.data);
        } catch (error) {
            console.error('Upload error:', error);
        } finally {
            setUploading(false);
        }
    };
    
    return (
        <div>
            <input type="file" onChange={handleFileChange} />
            <button onClick={handleUpload} disabled={uploading}>
                {uploading ? 'Uploading...' : 'Upload'}
            </button>
        </div>
    );
}

8.3 Cloud Storage

// AWS S3 upload
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

async function uploadToS3(file) {
    const params = {
        Bucket: process.env.S3_BUCKET,
        Key: `uploads/${Date.now()}-${file.originalname}`,
        Body: file.buffer,
        ContentType: file.mimetype
    };
    
    return await s3.upload(params).promise();
}