Blog
Wild & Free Tools

Using UUID for File Names in File Uploads

Last updated: March 2026 5 min read
Quick Answer

Table of Contents

  1. Why Original Filenames Are Dangerous
  2. The UUID File Upload Pattern
  3. UUID File Names in Python
  4. UUID Filenames on S3 / Cloud Storage
  5. UUID v7 for Ordered File Listings
  6. Frequently Asked Questions

When a user uploads a file named photo.jpg, storing it as photo.jpg on your server is a security problem. Path traversal attacks, name collisions between users, and leaking internal structure are all enabled by preserving original filenames. The solution is simple: generate a UUID v4, append the original extension, store that as the filename. This guide shows the complete pattern with code.

Why You Should Never Store Original Filenames

Path traversal: A malicious user uploads a file named ../../etc/passwd. If your code naively joins paths, this overwrites a system file.

Name collisions: Two users upload resume.pdf. The second upload overwrites the first. With UUID filenames, each upload gets its own unique path.

Information disclosure: Original filenames reveal user behavior — project-secret-v3-final-REAL.docx in your logs or CDN access logs exposes business information.

Extension abuse: A user uploads malware.php as an "image." If the original filename is preserved and served via a PHP-capable server, it executes as code.

UUID filenames fix all of these: unguessable, no collisions, no information leakage, no path traversal possible via the filename itself.

The UUID File Upload Pattern

// The pattern:
// 1. Accept file upload
// 2. Extract original extension (validated)
// 3. Generate UUID
// 4. Store as UUID + extension
// 5. Save original name + UUID mapping in database

// Node.js with multer:
import crypto from 'crypto';
import path from 'path';
import multer from 'multer';

const storage = multer.diskStorage({
  destination: 'uploads/',
  filename: (req, file, cb) => {
    const ext = path.extname(file.originalname).toLowerCase();
    const allowedExts = ['.jpg', '.jpeg', '.png', '.pdf', '.docx'];
    if (!allowedExts.includes(ext)) {
      return cb(new Error('File type not allowed'));
    }
    const uuid = crypto.randomUUID();
    cb(null, uuid + ext); // e.g., "550e8400-e29b-41d4-a716-446655440000.jpg"
  }
});

const upload = multer({ storage, limits: { fileSize: 10 * 1024 * 1024 } });

// Save the mapping:
app.post('/upload', upload.single('file'), async (req, res) => {
  await db.files.insert({
    uuid: req.file.filename.replace(/.[^.]+$/, ''), // UUID without ext
    originalName: req.file.originalname,
    uploadedBy: req.user.id,
    uploadedAt: new Date(),
  });
  res.json({ fileId: req.file.filename });
});
Sell Custom Apparel — We Handle Printing & Free Shipping

UUID File Names in Python (Flask / Django)

import uuid
import os
from pathlib import Path

ALLOWED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.pdf', '.docx'}

def secure_filename(original_name: str) -> str:
    ext = Path(original_name).suffix.lower()
    if ext not in ALLOWED_EXTENSIONS:
        raise ValueError(f"Extension not allowed: {ext}")
    return str(uuid.uuid4()) + ext

# Flask example:
from flask import request
from werkzeug.utils import secure_filename as ws_secure

@app.route('/upload', methods=['POST'])
def upload_file():
    file = request.files['file']
    filename = secure_filename(file.filename)  # our UUID function
    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

    # Save mapping to database:
    db.execute(
        'INSERT INTO uploads (uuid, original_name, user_id) VALUES (?, ?, ?)',
        (filename.split('.')[0], file.filename, current_user.id)
    )
    return jsonify({'fileId': filename})

UUID Filenames on S3, R2, and Cloud Storage

// AWS S3 — UUID as object key:
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import crypto from 'crypto';
import path from 'path';

async function uploadToS3(fileBuffer, originalName, mimeType) {
    const ext = path.extname(originalName).toLowerCase();
    const key = crypto.randomUUID() + ext;
    // e.g., "uploads/550e8400-e29b-41d4-a716-446655440000.jpg"
    const prefixedKey = "uploads/" + key;

    await s3.send(new PutObjectCommand({
        Bucket: process.env.S3_BUCKET,
        Key: prefixedKey,
        Body: fileBuffer,
        ContentType: mimeType,
        // Do NOT make objects public by default
    }));

    return prefixedKey; // Store this in your database
}

// Generate a pre-signed URL for the user to download:
import { GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const url = await getSignedUrl(s3, new GetObjectCommand({
    Bucket: process.env.S3_BUCKET,
    Key: storedKey,
}), { expiresIn: 3600 }); // URL expires in 1 hour

Pre-signed URLs are the right pattern for user file downloads — they expire, they require no authentication config in the CDN, and they keep your S3 bucket private.

UUID v7 for Time-Ordered File Listings

UUID v4 filenames sort randomly — you cannot reconstruct upload order from filenames alone without a database query.

UUID v7 filenames embed a timestamp — files sort chronologically by filename, which is useful for:

// Node.js with uuid v7:
import { v7 as uuidv7 } from 'uuid';
const filename = uuidv7() + ext;
// Files uploaded later always sort after files uploaded earlier

// S3 bucket listing is now in chronological order:
// 01956b10-... (older)
// 01956b13-... (newer)

Use UUID v7 filenames when file order matters to your application. Use UUID v4 when order does not matter and you want completely opaque, non-time-revealing filenames.

Generate UUIDs for File Upload Testing

Get 1 or 10 UUID v4 filenames instantly from the Cheetah UUID Generator — use as mock file keys to test your upload storage logic.

Open Free UUID Generator

Frequently Asked Questions

Why should I use UUID for file upload names?

Original filenames are unsafe — they enable path traversal attacks, name collisions between users, and information disclosure. UUID filenames are unguessable, guaranteed unique, and reveal nothing about the file's origin or content.

Should I keep the original file extension when using a UUID filename?

Yes, but validate it. Keep the extension for MIME type hints and browser rendering. But validate the extension against an allowlist — never trust the extension the user provides without checking the actual file content type.

How do I let users download files by their original name?

Store the original name in your database alongside the UUID filename. When serving the file, set the Content-Disposition header: Content-Disposition: attachment; filename="original-name.pdf"

Is UUID v4 or v7 better for S3 object keys?

UUID v7 if you want chronological ordering of objects by key. UUID v4 if ordering does not matter and you want completely unpredictable keys. UUID v4 also distributes more evenly across S3 partitions, which can be marginally better for extremely high write throughput.

Can two uploaded files get the same UUID filename?

Cryptographically impossible in practice. UUID v4 has 122 bits of randomness — the probability of collision across billions of uploads is negligible. In production systems, UUID collisions are not a concern.

Jennifer Hayes
Jennifer Hayes Business Documents & PDF Writer

Jennifer spent a decade as an executive assistant handling every type of business document imaginable.

More articles by Jennifer →
Launch Your Own Clothing Brand — No Inventory, No Risk