# Forms with File Upload

Learn how to create forms that accept file uploads including images, documents, and videos. Available on Pro and Agency & Enterprise. Keep each submission (files plus form fields) at about ~100 MB or under.

### File Upload Limits

**Pro / Agency & Enterprise:** File uploads are available. Maximum ~100 MB per submission for all files combined, and for the full request payload (files + other form fields). Cloudflare also rejects requests over ~100 MB.

**Basic (free):** File uploads are not available. Team file storage is 0 GB.

**Pro storage quota:** 5 GB per team. When the quota is full, new uploads are rejected until you free space or contact support.

**Supported File Types:**

- Images: JPG, PNG, GIF, WebP
- Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, CSV
- Videos: MP4, MOV, AVI, WebM, MKV, WMV, FLV, 3GP

## Implementation

Create a form with file upload fields. Make sure to include `enctype="multipart/form-data"` in your form tag.

#### Form with File Upload

```
<form action="https://myformcapture.com/f/YOUR_FORM_UUID_HERE" method="POST" enctype="multipart/form-data">
  <input type="text" name="name" placeholder="Your Name" required>
  <input type="email" name="email" placeholder="Your Email" required>
  <input type="tel" name="phone" placeholder="Phone Number">

  <label for="resume">Upload Resume</label>
  <input type="file" name="resume" id="resume" accept=".pdf,.doc,.docx">

  <label for="documents">Upload Documents (Multiple)</label>
  <input type="file" name="documents[]" id="documents" multiple>

  <label for="photo">Upload Photo</label>
  <input type="file" name="photo" id="photo" accept="image/*">

  <label for="video">Upload Video</label>
  <input type="file" name="video" id="video" accept="video/*">

  <button type="submit">Submit</button>
</form>
```

#### Important Notes:

- Always include `enctype="multipart/form-data"` for file uploads
- Use `multiple` attribute to allow multiple file selection
- Use `accept` attribute to restrict file types (optional but recommended)
- Total limit: ~100 MB per submission (all files + form fields)
- Requires Pro or Agency & Enterprise

Use JavaScript with FormData to handle file uploads via AJAX, including progress tracking.

#### Form with AJAX File Upload

```
<form id="upload-form">
  <input type="text" name="name" placeholder="Your Name" required>
  <input type="email" name="email" placeholder="Your Email" required>
  <input type="tel" name="phone" placeholder="Phone Number">

  <label for="resume">Upload Resume</label>
  <input type="file" name="resume" id="resume" accept=".pdf,.doc,.docx">

  <label for="documents">Upload Documents (Multiple)</label>
  <input type="file" name="documents[]" id="documents" multiple>

  <!-- Progress bar -->
  <div id="progress-container" style="display: none;">
    <div class="progress-bar">
      <div id="progress-bar" style="width: 0%; background: #3b82f6; height: 20px; transition: width 0.3s;"></div>
    </div>
    <span id="progress-text">0%</span>
  </div>

  <button type="submit">Submit</button>
</form>

<script>
document.getElementById('upload-form').addEventListener('submit', async function(e) {
  e.preventDefault();

  const form = e.target;
  const formData = new FormData(form);
  const maxSizeMB = 100;
  const maxBytes = maxSizeMB * 1024 * 1024;

  // Client-side total size check
  let totalSize = 0;
  for (const [key, value] of formData.entries()) {
    if (value instanceof File) totalSize += value.size;
  }
  if (totalSize > maxBytes) {
    alert(`Total file size exceeds ${maxSizeMB} MB limit. Please reduce file sizes.`);
    return;
  }

  const progressContainer = document.getElementById('progress-container');
  const progressBar = document.getElementById('progress-bar');
  const progressText = document.getElementById('progress-text');
  progressContainer.style.display = 'block';

  try {
    const xhr = new XMLHttpRequest();

    xhr.upload.addEventListener('progress', function(e) {
      if (e.lengthComputable) {
        const percent = Math.round((e.loaded / e.total) * 100);
        progressBar.style.width = percent + '%';
        progressText.textContent = percent + '%';
      }
    });

    xhr.addEventListener('load', function() {
      if (xhr.status >= 200 && xhr.status < 300) {
        alert('Form submitted successfully!');
        form.reset();
        progressContainer.style.display = 'none';
      } else {
        let message = 'Upload failed. Please try again.';
        try {
          const data = JSON.parse(xhr.responseText);
          if (data.error) message = data.error;
        } catch (_) {}
        alert(message);
        progressContainer.style.display = 'none';
      }
    });

    xhr.addEventListener('error', function() {
      alert('Network error. Please try again.');
      progressContainer.style.display = 'none';
    });

    xhr.open('POST', 'https://myformcapture.com/f/YOUR_FORM_UUID_HERE');
    xhr.setRequestHeader('Accept', 'application/json');
    xhr.send(formData);
  } catch (err) {
    alert('Upload failed. Please try again.');
    progressContainer.style.display = 'none';
  }
});
</script>
```
