I'm building a front-end form with image submissions. The form creates then a new post:

...process post...
$application_id = wp_insert_post($application);

I then use media_handle_upload to upload image and attach them to the post:

...process file...
$file_id = media_handle_upload("upload_file", $application_id);

It works fine — my issue is that everything happens on submit, so the files is uploading only after the user clicks the submit button.

Is there a way to upload the images straight when the user adds them to the input field? What happens if the user then abandons the form — how would I delete the images then?

  • Is there a reason you don't like the way it works now? I makes sense to NOT upload the media files until the post has been submitted because then you're not stuck with the extra issue of deleting the images if the user aborts. Mar 26 at 2:52
  • @TonyDjukic the reason is that it's additional wait if images are uploaded on submit and most services upload immediately so that's what users are used to
    – Runnick
    Mar 27 at 23:09
  • 1
    I think then that you'd need to have a custom DB table or add as attachment meta_data whether or not the form was completed, then run CRON to go through the attachments meta_data and delete the images that were uploaded without a full form submission. Either way you're looking at a two stage process and then a third clean-up process. Apr 1 at 0:38

2 Answers 2


Getting your form to upload an image as soon as it is selected rather that submitted is pretty straightforward, as you can submit the form whenever a field changes like this:

<form action="http://example.com" method="post" action="#">
  <input type="file" onchange="form.submit()" />

The difficulty is in keeping track of this at the server end. The user may change his mind and select another image. So you only want to keep the things that are in the form when the user clicks on the submit button. If there is only one image this is still fairly easy: delete all attachments you created except for the last one. But if there are multiple file input fields your administration becomes slightly more complicated.

However, if you look at media_handle_upload you see that there is a possibility to pass $post_data to the file you are uploading. You could, for instance, use the excerpt field (temporarily) to store you administration. To get this admin data from the form to the server you could use hidden fields. Your form could look something like this:

<form action="http://example.com" method="post" action="#">
  // hidden field with the id of the post that is generated
  <input type="hidden" name="post_id" id="post_id" value="99999" />
  <input type="file" name="image_upload1" id="image_upload1" onchange="form.submit()" />
  <input type="file" name="image_upload2" id="image_upload2" onchange="form.submit()" />
  <input id="submit_my_image" name="submit_my_image" type="submit" value="Upload" />

Now, when the form is submitted (either by javascript or a submit action) there is data arriving at the server telling you the name of a file to be uploaded. You create the attachment to the post:

$post_data['excerpt'] = 'image1';
$file_id = media_handle_upload("image_upload1", $application_id, $post_data);
$post_data['excerpt'] = 'image2';
$file_id = media_handle_upload("image_upload2", $application_id, $post_data);

If the user changes his mind often you will have quite a lot of attachments, with the same $post_data but different time stamps. You can do the clean up by looping through all attachments at the real submit. Or you can do a test whether a file with the same excerpt already exist before you call to media_handle_upload above.

Now you must distinguish between the javascript submits and the final submit. My suggestion would be to change the name of the submit button on hover/click. At this point you could also clean up de excerpts.

Now, what if the user abandons the process altogether? The above will only work if you create a post the moment you serve the form (or at least at the first image upload, as you cannot have an attachment to a non existing post). The trick here is to define your own post_status, which you set during your call to wp_insert_post. Only when the user submits you change the post_status to draft or publish. Periodically you do an automated clean up of all posts, including attachments, of that self-defined type that are more than three hours old or so.

  • Some great insights here, thanks!
    – Runnick
    Apr 3 at 12:08
  • 1
    I forgot something. On the final button click, the form will still try to submit the file. So you will have to disable sending files on button click, as you already have those files after the onchange action.
    – cjbj
    Apr 4 at 10:02

try below the code front end form with media handle upload in Wordpress.

<form id="post-submission-form" method="post" enctype="multipart/form-data">
    <input type="file" id="upload_file" name="upload_file" accept="image/*" required>
    <input type="submit" value="Submit Post">
<div id="image-preview"></div>

jQuery(document).ready(function($) {
    $('#upload_file').change(function() {
        var file_data = $(this).prop('files')[0];
        var form_data = new FormData();
        form_data.append('file', file_data);

            url: ajaxurl, // WordPress AJAX URL
            type: 'POST',
            data: form_data,
            contentType: false,
            processData: false,
            success: function(response) {
                $('#image-preview').html('<img src="' + response + '" />');

    $('#post-submission-form').submit(function(e) {
        var form = $(this);
        var formData = new FormData(form[0]);

            url: ajaxurl,
            type: 'POST',
            data: formData,
            contentType: false,
            processData: false,
            success: function(response) {
                // Handle post submission response here


add_action('wp_ajax_upload_image', 'upload_image_callback');
add_action('wp_ajax_nopriv_upload_image', 'upload_image_callback');

function upload_image_callback() {
    $uploaded_file = $_FILES['file'];
    $upload_overrides = array('test_form' => false);
    $movefile = wp_handle_upload($uploaded_file, $upload_overrides);

    if ($movefile && !isset($movefile['error'])) {
        echo $movefile['url'];
    } else {
        echo 'Error uploading file.';

  • Thanks! My idea is to upload on change though and delete if form is not submitted.
    – Runnick
    Mar 28 at 11:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.