# Storing Uploaded Files and Serving Them in Express

# Where uploaded files are stored

When a user uploads a file via an API (e.g., using `multipart/form-data`), the backend needs to decide **where to persist it**.

### Typical flow:

1.  Client uploads file → API endpoint
    
2.  Middleware (like `multer`) processes the file
    
3.  File is stored either:
    
    *   Locally (disk)
        
    *   Remotely (cloud storage)
        

### Example using `multer` (local storage):

```javascript
import multer from "multer";

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "uploads/");
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + "-" + file.originalname);
  },
});

const upload = multer({ storage });
```

This stores files in a local `uploads/` directory.

# Local storage vs external storage concept

Choosing storage is an **architectural decision**, not just an implementation detail.

### Local Storage (Disk)

**Pros:**

*   Simple setup
    
*   Fast access (low latency)
    
*   No external dependencies
    

**Cons:**

*   Not scalable across multiple servers
    
*   Risk of data loss on server crash
    
*   Difficult to manage backups
    

### External Storage (Cloud)

Popular services:

*   Amazon S3
    
*   Cloudinary
    
*   Google Cloud Storage
    

**Pros:**

*   Highly scalable
    
*   Durable and reliable
    
*   CDN support for fast delivery
    

**Cons:**

*   Requires setup and credentials
    
*   Slightly higher latency
    
*   Costs involved
    

# Serving static files in Express

Once files are stored locally, you need to **serve them over HTTP**.

### Basic setup:

```javascript
import express from "express";

const app = express();

app.use("/uploads", express.static("uploads"));
```

### What this does:

*   Maps `/uploads` URL path → `uploads/` folder
    
*   Any file inside `uploads/` becomes publicly accessible  
    

# Accessing uploaded files via URL

If a file is stored as:

```plaintext
uploads/1714738293-profile.png
```

You can access it at:

```plaintext
http://localhost:3000/uploads/1714738293-profile.png
```

### Example API response:

```plaintext
{
  "imageUrl": "http://localhost:3000/uploads/1714738293-profile.png"
}
```

This URL can be used directly in frontend apps (`<img src=... />`).

# Security considerations for uploads

*   Maps `/uploads` URL path → `uploads/` folder
    
*   Any file inside `uploads/` becomes publicly accessible
    

* * *

## 🌐 Accessing Uploaded Files via URL

If a file is stored as:

```plaintext
uploads/1714738293-profile.png
```

You can access it at:

```plaintext
http://localhost:3000/uploads/1714738293-profile.png
```

### Example API response:

```plaintext
{
  "imageUrl": "http://localhost:3000/uploads/1714738293-profile.png"
}
```

This URL can be used directly in frontend apps (`<img src=... />`).

# Security Considerations for File Uploads

This is where most developers make mistakes. File uploads are a **major attack vector**.

### Validate File Types

Never trust `file.mimetype` blindly.

```javascript
const allowedTypes = ["image/png", "image/jpeg"];

if (!allowedTypes.includes(file.mimetype)) {
  throw new Error("Invalid file type");
}
```

### Limit File Size

```javascript
const upload = multer({
  storage,
  limits: { fileSize: 2 * 1024 * 1024 }, // 2MB
});
```

Prevents DoS via large uploads.

### Avoid Executable Files

Never allow:

*   `.js`
    
*   `.exe`
    
*   `.sh`  
    

These can be executed on your server if misconfigured.

### Rename Files Safely

Avoid using original filenames directly.

✔️ Good:

```plaintext
timestamp-randomstring.png
```

❌ Bad:

```plaintext
../../../etc/passwd
```

### Use Separate Storage Server (Production)

Serving files directly from your API server:

*   Increases load
    
*   Reduces scalability  
    

Instead:

*   Upload → Cloud (e.g., S3)
    
*   Serve via CDN  
    

### Authentication (if needed)

Not all files should be public.

Options:

*   Signed URLs (S3)
    
*   Auth middleware before serving files
