How7oHow7o
  • Home
  • Tools
    • All Tools
    • Image Tools
    • Text & String Tools
    • Video Tools
    • Developer Tools
    • PDF Tools
    • Calculators & More
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: How to Upload Files via Ajax with jQuery
Share
Notification Show More
Font ResizerAa
How7oHow7o
Font ResizerAa
  • Tools
  • Prank Screens
  • Learn
  • Blog
Search
  • Home
  • Tools
    • All Tools
    • Image Tools
    • Text & String Tools
    • Video Tools
    • Developer Tools
    • PDF Tools
    • Calculators & More
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Web Development > How to Upload Files via Ajax with jQuery
Web Development

How to Upload Files via Ajax with jQuery

how7o
By how7o
Last updated: May 23, 2026
4 Min Read
Upload files via Ajax with jQuery using FormData
SHARE

To upload image (or any) files via Ajax with jQuery, wrap the form in new FormData(this) and pass that to $.ajax with contentType: false and processData: false. The .serialize() approach silently drops file inputs — FormData is what carries multipart payloads.

Contents
  • The fix — use FormData
  • Server side (PHP)
  • Show upload progress
  • Vanilla fetch alternative
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-05-17 with jQuery 3.7. Originally published 2022-09-21, rewritten and updated 2026-05-17.

The fix — use FormData

<form id="user-signup-form" enctype="multipart/form-data" action="/upload" method="post">
    <input type="text"     name="username">
    <input type="email"    name="email">
    <input type="password" name="password">
    <input type="file"     name="profile_picture" accept="image/*">
    <button type="submit">Register</button>
</form>

<script>
$('#user-signup-form').on('submit', function (e) {
    e.preventDefault();

    const formData = new FormData(this);

    $.ajax({
        type:        'POST',
        url:         $(this).attr('action'),
        data:        formData,
        cache:       false,
        contentType: false,
        processData: false,
    })
    .done(function (data) {
        console.log('Uploaded:', data);
    })
    .fail(function (xhr) {
        console.error('Upload failed:', xhr.statusText);
    });
});
</script>

new FormData(this) walks the form and grabs every field, including the file. contentType: false lets the browser set the multipart boundary; processData: false stops jQuery from URL-encoding the binary data.

jQuery Ajax file upload — FormData, contentType/processData false, upload progress, fetch alternative

Server side (PHP)

<?php
// /upload — receives the multipart POST
if (isset($_FILES['profile_picture'])) {
    $file = $_FILES['profile_picture'];
    if ($file['error'] === UPLOAD_ERR_OK) {
        move_uploaded_file($file['tmp_name'], 'uploads/' . basename($file['name']));
        echo json_encode(['ok' => true]);
        exit;
    }
}
http_response_code(400);
echo json_encode(['ok' => false]);

Show upload progress

$.ajax({
    type:        'POST',
    url:         '/upload',
    data:        formData,
    cache:       false,
    contentType: false,
    processData: false,
    xhr: function () {
        const xhr = new window.XMLHttpRequest();
        xhr.upload.addEventListener('progress', function (e) {
            if (e.lengthComputable) {
                const pct = Math.round((e.loaded / e.total) * 100);
                $('#progress').text(pct + '%');
            }
        });
        return xhr;
    },
});

Vanilla fetch alternative

document.getElementById('user-signup-form').addEventListener('submit', async (e) => {
    e.preventDefault();

    const res = await fetch(e.target.action, {
        method: 'POST',
        body:   new FormData(e.target),
    });

    const data = await res.json();
    console.log(data);
});

fetch with a FormData body is one line — no contentType/processData gymnastics needed. For new code without jQuery, this is the cleanest form.

Frequently asked questions

Why does $(form).serialize() lose file inputs?

.serialize() only handles successful form controls that have string values — text, select, checkbox, etc. <input type="file"> values are File objects, not strings. FormData(form) walks the form and grabs every field including files, then jQuery’s $.ajax sends it as a multipart request the same way a non-Ajax submit would.

Why contentType: false and processData: false?

contentType: false tells jQuery not to set the Content-Type header — the browser sets it to multipart/form-data; boundary=... with a generated boundary string. processData: false tells jQuery not to URL-encode the data (it would default to application/x-www-form-urlencoded, which can’t carry binary file content). Both are required for file uploads.

How do I show upload progress?

Override the XHR via xhr: xhr: function () { const x = new window.XMLHttpRequest(); x.upload.addEventListener('progress', e => { if (e.lengthComputable) console.log(e.loaded / e.total); }); return x; }. The progress event fires while bytes are uploading; the percentage is loaded / total.

Should I bother with jQuery or use fetch?

For new code, fetch: fetch(url, { method: 'POST', body: new FormData(form) }) is one line and doesn’t need the contentType/processData dance — fetch respects FormData natively. Use jQuery only when you’re already in a jQuery codebase.

Related guides

  • How to Upload Only Image Files Using PHP
  • How to Open a File Dialog When Clicking a Button
  • How to Convert an Image to a Base64 String in JavaScript

References

jQuery $.ajax: api.jquery.com/jquery.ajax. MDN FormData: developer.mozilla.org/en-US/docs/Web/API/FormData. MDN XMLHttpRequest.upload: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/upload.

TAGGED:ajaxformsJavaScriptjQuery

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article Disable binary logging in MySQL or MariaDB How to Disable Binary Logging in MySQL or MariaDB
Next Article Securely upload only image files in PHP How to Upload Only Image Files Using PHP
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

You Might Also Like

Laravel Eloquent delete record — trash-bin icon next to User::destroy code snippet
Web Development

How to Delete a Record with Laravel Eloquent (4 Methods)

6 Min Read
Fix CSS page breaks not working with HTML tables
Web Development

Why CSS Page Breaks Don’t Work in HTML Tables (and How to Fix It)

5 Min Read
Prevent tab key from focusing on a link with tabindex=-1
Web Development

How to Skip a Link When Pressing Tab (tabindex=-1)

5 Min Read
Get the selected radio button value with jQuery
Web Development

How to Get the Selected Radio Button Value in jQuery

3 Min Read
How7oHow7o

Free browser-based tools, prank screens, and step-by-step tech tutorials. No signup, nothing uploaded.

  • Private by design — your files never leave your device
  • Instant — no signup, no install, no waiting
  • Always free — no trials, no watermarks, no paywalls

Tools

  • PDF Editor
  • Image Upscaler
  • JPEG Compressor
  • Password Generator
  • QR Code Generator
  • Video Trimmer
  • See all tools →

Pranks

  • Cracked Screen Prank
  • Fake Blue Screen (BSOD)
  • Fake Disk Format
  • Fake Low Battery
  • Fake Nintendo Switch Update Screen
  • Fake PlayStation Update Screen
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?