How to Upload Files Using Putfile.dev

File uploads are a common requirement in modern web applications, but implementing them can be surprisingly complex. Putfile.dev eliminates this complexity by providing a simple, powerful API that handles all the heavy lifting. In this comprehensive guide, you'll learn how to implement file uploads in your application—from basic setup to production-ready implementations.

What You'll Build

By the end of this tutorial, you'll know how to:

  • Set up a Putfile.dev account and generate API keys
  • Implement basic file uploads with vanilla JavaScript
  • Build a file upload component in React
  • Handle file uploads in Next.js applications
  • Implement drag-and-drop functionality
  • Display upload progress and handle errors

Prerequisites

Before you begin, make sure you have:

  • Node.js (v16 or higher) installed
  • Basic understanding of JavaScript/TypeScript
  • A Putfile.dev account (sign up at putfile.dev)

Step 1: Initial Setup

Create Your Putfile.dev Account

  1. Visit putfile.dev and sign up for a free account
  2. Navigate to your dashboard
  3. Generate a new API key
  4. Copy and save your API key securely

Install the Putfile Library

npm install @putfiledev/putfile

Or with yarn:

yarn add @putfiledev/putfile

Step 2: Basic File Upload with Vanilla JavaScript

Let's start with the simplest implementation—a basic file upload using vanilla JavaScript.

HTML Structure

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Putfile Upload Demo</title>
</head>
<body>
  <div class="upload-container">
    <input type="file" id="fileInput" />
    <button id="uploadBtn">Upload File</button>
    <div id="status"></div>
    <div id="result"></div>
  </div>

  <script type="module" src="./upload.js"></script>
</body>
</html>

JavaScript Implementation

import { putfile } from '@putfiledev/putfile';

// Initialize with your API key
const PUTFILE_API_KEY = 'your_api_key_here';

const fileInput = document.getElementById('fileInput');
const uploadBtn = document.getElementById('uploadBtn');
const status = document.getElementById('status');
const result = document.getElementById('result');

uploadBtn.addEventListener('click', async () => {
  const file = fileInput.files[0];
  
  if (!file) {
    status.textContent = 'Please select a file first';
    return;
  }

  try {
    status.textContent = 'Uploading...';
    
    const response = await putfile(file, {
      apiKey: PUTFILE_API_KEY,
    });
    
    status.textContent = 'Upload successful!';
    result.innerHTML = `
      <p>File URL: <a href="${response.url}" target="_blank">${response.url}</a></p>
      <p>File ID: ${response.id}</p>
    `;
  } catch (error) {
    status.textContent = `Upload failed: ${error.message}`;
    console.error('Upload error:', error);
  }
});

That's it! You now have a working file upload system.

Step 3: React Implementation

For React applications, let's build a reusable file upload component with progress tracking.

Basic React Component

import { useState } from 'react';
import { putfile } from '@putfiledev/putfile';

export function FileUploader() {
  const [file, setFile] = useState(null);
  const [uploading, setUploading] = useState(false);
  const [uploadedUrl, setUploadedUrl] = useState('');
  const [error, setError] = useState('');

  const handleFileChange = (e) => {
    setFile(e.target.files[0]);
    setError('');
  };

  const handleUpload = async () => {
    if (!file) {
      setError('Please select a file');
      return;
    }

    setUploading(true);
    setError('');

    try {
      const result = await putfile(file, {
        apiKey: process.env.NEXT_PUBLIC_PUTFILE_API_KEY,
      });

      setUploadedUrl(result.url);
      setFile(null);
    } catch (err) {
      setError(`Upload failed: ${err.message}`);
    } finally {
      setUploading(false);
    }
  };

  return (
    <div className="file-uploader">
      <input
        type="file"
        onChange={handleFileChange}
        disabled={uploading}
      />
      
      <button
        onClick={handleUpload}
        disabled={!file || uploading}
      >
        {uploading ? 'Uploading...' : 'Upload File'}
      </button>

      {error && <p className="error">{error}</p>}
      
      {uploadedUrl && (
        <div className="success">
          <p>File uploaded successfully!</p>
          <a href={uploadedUrl} target="_blank" rel="noopener noreferrer">
            View File
          </a>
        </div>
      )}
    </div>
  );
}

Advanced Component with Progress

import { useState } from 'react';
import { putfile } from '@putfiledev/putfile';

export function AdvancedFileUploader() {
  const [file, setFile] = useState(null);
  const [progress, setProgress] = useState(0);
  const [uploading, setUploading] = useState(false);
  const [uploadedUrl, setUploadedUrl] = useState('');

  const handleUpload = async () => {
    if (!file) return;

    setUploading(true);
    setProgress(0);

    try {
      const result = await putfile(file, {
        apiKey: process.env.NEXT_PUBLIC_PUTFILE_API_KEY,
        onProgress: (progressEvent) => {
          const percentCompleted = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          setProgress(percentCompleted);
        },
      });

      setUploadedUrl(result.url);
    } catch (error) {
      console.error('Upload failed:', error);
    } finally {
      setUploading(false);
    }
  };

  return (
    <div>
      <input
        type="file"
        onChange={(e) => setFile(e.target.files[0])}
        disabled={uploading}
      />
      
      <button onClick={handleUpload} disabled={!file || uploading}>
        Upload
      </button>

      {uploading && (
        <div className="progress-bar">
          <div 
            className="progress-fill"
            style={{ width: `${progress}%` }}
          >
            {progress}%
          </div>
        </div>
      )}

      {uploadedUrl && <p>File URL: {uploadedUrl}</p>}
    </div>
  );
}

Step 4: Next.js Implementation

For Next.js applications, you can implement file uploads using both client-side and server-side approaches.

Client-Side Upload

'use client';

import { useState } from 'react';
import { putfile } from '@putfiledev/putfile';

export default function UploadPage() {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploadResult, setUploadResult] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    if (!selectedFile) return;

    try {
      const result = await putfile(selectedFile, {
        apiKey: process.env.NEXT_PUBLIC_PUTFILE_API_KEY,
      });
      
      setUploadResult(result);
    } catch (error) {
      console.error('Upload error:', error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="file"
        onChange={(e) => setSelectedFile(e.target.files[0])}
      />
      <button type="submit">Upload</button>
      
      {uploadResult && (
        <div>
          <p>Success! File uploaded to:</p>
          <a href={uploadResult.url}>{uploadResult.url}</a>
        </div>
      )}
    </form>
  );
}

Server Action Implementation

// app/actions.ts
'use server';

import { putfile } from '@putfiledev/putfile';

export async function uploadFile(formData: FormData) {
  const file = formData.get('file') as File;
  
  if (!file) {
    return { error: 'No file provided' };
  }

  try {
    const result = await putfile(file, {
      apiKey: process.env.PUTFILE_API_KEY,
    });
    
    return { success: true, url: result.url };
  } catch (error) {
    return { error: 'Upload failed' };
  }
}
// app/upload/page.tsx
'use client';

import { uploadFile } from '../actions';

export default function ServerUploadPage() {
  const handleSubmit = async (formData: FormData) => {
    const result = await uploadFile(formData);
    
    if (result.success) {
      console.log('File uploaded:', result.url);
    } else {
      console.error('Error:', result.error);
    }
  };

  return (
    <form action={handleSubmit}>
      <input type="file" name="file" required />
      <button type="submit">Upload File</button>
    </form>
  );
}

Step 5: Drag and Drop Implementation

Enhance user experience with drag-and-drop functionality:

import { useState } from 'react';
import { putfile } from '@putfiledev/putfile';

export function DragDropUploader() {
  const [isDragging, setIsDragging] = useState(false);
  const [uploadedUrl, setUploadedUrl] = useState('');

  const handleDragOver = (e) => {
    e.preventDefault();
    setIsDragging(true);
  };

  const handleDragLeave = (e) => {
    e.preventDefault();
    setIsDragging(false);
  };

  const handleDrop = async (e) => {
    e.preventDefault();
    setIsDragging(false);

    const files = e.dataTransfer.files;
    if (files.length === 0) return;

    try {
      const result = await putfile(files[0], {
        apiKey: process.env.NEXT_PUBLIC_PUTFILE_API_KEY,
      });
      
      setUploadedUrl(result.url);
    } catch (error) {
      console.error('Upload error:', error);
    }
  };

  return (
    <div
      onDragOver={handleDragOver}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
      style={{
        border: `2px dashed ${isDragging ? '#0070f3' : '#ccc'}`,
        padding: '40px',
        textAlign: 'center',
        backgroundColor: isDragging ? '#f0f8ff' : 'white',
      }}
    >
      <p>Drag and drop a file here, or click to select</p>
      <input
        type="file"
        onChange={async (e) => {
          const file = e.target.files[0];
          if (file) {
            const result = await putfile(file, {
              apiKey: process.env.NEXT_PUBLIC_PUTFILE_API_KEY,
            });
            setUploadedUrl(result.url);
          }
        }}
        style={{ display: 'block', margin: '20px auto' }}
      />
      
      {uploadedUrl && (
        <div>
          <p>✅ File uploaded successfully!</p>
          <a href={uploadedUrl} target="_blank" rel="noopener">
            {uploadedUrl}
          </a>
        </div>
      )}
    </div>
  );
}

Best Practices

1. Environment Variables

Never hardcode your API key. Use environment variables:

# .env.local
NEXT_PUBLIC_PUTFILE_API_KEY=your_api_key_here

2. File Validation

Always validate files before uploading:

function validateFile(file) {
  const maxSize = 10 * 1024 * 1024; // 10MB
  const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
  
  if (file.size > maxSize) {
    throw new Error('File is too large (max 10MB)');
  }
  
  if (!allowedTypes.includes(file.type)) {
    throw new Error('File type not allowed');
  }
  
  return true;
}

3. Error Handling

Implement comprehensive error handling:

try {
  const result = await putfile(file, { apiKey });
  // Success handling
} catch (error) {
  if (error.response?.status === 413) {
    console.error('File too large');
  } else if (error.response?.status === 401) {
    console.error('Invalid API key');
  } else {
    console.error('Upload failed:', error.message);
  }
}

4. User Feedback

Provide clear feedback throughout the upload process:

  • Show loading states during upload
  • Display progress bars for large files
  • Show success/error messages
  • Provide uploaded file URLs

Common Pitfalls to Avoid

Issue Problem Solution
Exposed API Keys Hardcoding API keys in frontend Use environment variables
No File Validation Uploading invalid/large files Validate before upload
Poor UX No upload progress feedback Implement progress tracking
No Error Handling Silent failures confuse users Show clear error messages

Next Steps

Now that you know how to upload files with Putfile.dev, you can:

  • Customize upload options: Add metadata, set custom filenames, configure expiration
  • Implement image optimization: Use Putfile's built-in image transformation features
  • Build file management: Create galleries, file browsers, and deletion workflows
  • Explore advanced features: Learn about webhooks, CDN integration, and analytics

Conclusion

Putfile.dev makes file uploads simple and reliable. With just a few lines of code, you've implemented a production-ready file upload system that scales automatically, includes built-in security, and provides a great user experience.

Ready to build something amazing? Get started with Putfile.dev →