I'm using wordpress with ajax in a frontend form and I'd need support for handling and uploading the featured image. My problem is specifically about the featured image. My html is something like:
<form id="msform" action="#" method="post" enctype="multipart/form-data">
//inputs of various nature
<input type="file" name="main_image" id="main_image" multiple="false" value="" accept=".png, .jpg, .jpeg, .gif"/>
<input type="submit" class="submit" value="Publish"/>
</form>
I send data to a php function (following Wordpress methods) through this jquery:
function apfaddpost() {
var formData = $('#msform').serialize();
formData.append('main_image', $('#main_image')[0].files[0]); //here should be the problem
jQuery.ajax({
type: 'POST',
url: apfajax.ajaxurl,
data: formData + '&action=apf_addpost', //here I send data to the php function calling the specific action
processData: false,
contentType: false
success: function(data, textStatus, XMLHttpRequest) {
var id = '#apf-response';
jQuery(id).html('');
jQuery(id).append(data);
resetvalues();
},
error: function(MLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});
}
My function php is something like
function apf_addpost() {
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
$file_handler = 'main_image';
$attach_id = media_handle_upload($file_handler,$pid );
update_post_meta($pid,'_thumbnail_id',$attach_id);
}
Important to say: all the other data like title, description, tags are correctly serialized and sent. The problem is for the image. I've tried also to use the $_FILES[]
handler without success and I suppose that my ajax code is not so great then. Can you help me? If you have any other workaround for this issue please share! Thanks in advance.
[SOLVED] EDIT
Thanks to the answers below I've just changed my ajax into
function apfaddpost() {
var fd = new FormData($('#msform')[0]);
fd.append( "main_image", $('#main_image')[0].files[0]);
fd.append( "action", 'apf_addpost');
//Append here your necessary data
jQuery.ajax({
type: 'POST',
url: apfajax.ajaxurl,
data: fd,
processData: false,
contentType: false,
success: function(data, textStatus, XMLHttpRequest) {
var id = '#apf-response';
jQuery(id).html('');
jQuery(id).append(data);
resetvalues();
},
error: function(MLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});
}
I've discovered that FormData()
allows to serialize files, thing that .serialize()
method doesn't. Known that, it has been simple to move on.
Thanks.
Please Try :
I have modify your code.
Jquery (added FormData() and append)
function apfaddpost() {
var fd = new FormData();
fd.append( "main_image", $('#main_image')[0].files[0]);
fd.append( "action", 'apf_addpost');
//Append here your necessary data
jQuery.ajax({
type: 'POST',
url: apfajax.ajaxurl,
data: fd,
processData: false,
contentType: false
success: function(data, textStatus, XMLHttpRequest) {
var id = '#apf-response';
jQuery(id).html('');
jQuery(id).append(data);
resetvalues();
},
error: function(MLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});
}
in function.php
I have added file upload code
/******FILE UPLOAD*****************/
function upload_user_file( $file = array() ) {
require_once( ABSPATH . 'wp-admin/includes/admin.php' );
$file_return = wp_handle_upload( $file, array('test_form' => false ) );
if( isset( $file_return['error'] ) || isset( $file_return['upload_error_handler'] ) ) {
return false;
} else {
$filename = $file_return['file'];
$attachment = array(
'post_mime_type' => $file_return['type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
'post_content' => '',
'post_status' => 'inherit',
'guid' => $file_return['url']
);
$attachment_id = wp_insert_attachment( $attachment, $file_return['url'] );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename );
wp_update_attachment_metadata( $attachment_id, $attachment_data );
if( 0 < intval( $attachment_id ) ) {
return $attachment_id;
}
}
return false;
}
now modify your function apf_addpost()
in function.php
function apf_addpost() {
foreach( $_FILES as $file )
{
if( is_array( $file ) ) {
$attach_id =upload_user_file(); //Call function
update_post_meta($pid,'_thumbnail_id',$attach_id);
}
}
}
For ajax upload in WordPress these are a few things to note;
For sending images a form
with enctype="multipart/form-data"
is necessary. enctype
attribute specifies how the form-data is encoded during form submission. By default its application/x-www-form-urlencoded
as we are doing a file upload we change the value to multipart/form-data
.
<form action="" method="post" enctype="multipart/form-data">
<input type="file" id="image_upload">
<button type="button" id="image_upload_btn">Update</button>
</form>
$("#image_upload_btn").click(function (e) {
e.preventDefault();
var fd = new FormData();
var files = $("#image_upload")[0].files;
fd.append("file", files[0]);
fd.append("action", "upload_image"); // your ajax function
if (files.length > 0) {
jQuery.ajax({
type: "POST",
url: ajax_url, // var ajax_url = " <?= admin_url('admin-ajax.php'); ?>"; pass it in the php file
processData: false,
contentType: false,
data: fd,
beforeSend: function () {
// Any code you like
},
success: function (response) {
// Success code
},
error: function (request, status, error) {
console.log(error);
alert(request.responseText);
},
});
}
});
We need to use a FormData()
interface to construct a set of key/value pairs that represent our form fields and values(here it's our image file). This helps to easily transfer the file using ajax.
As we are using WordPress, in addition to the image file we also add in the action
parameter as well in the FormData()
.
Another important thing to note here is the processData
and contentType
without which you are likely to face Uncaught TypeError: Illegal invocation
.
processData
?The data passed in the data option as the object is processed and transformed into a query string for ajax by default, as we are doing a file upload we want that to be false.
contentType
?By default it's application/x-www-form-urlencoded; charset=UTF-8
for file uploads we have to explicitly change it to false to unset any content-type header.
function upload_image()
{
if (isset($_FILES['file']['name'])) {
$filename = $_FILES['file']['name'];
$location = ;// Your desired location
$imageFileType = pathinfo($location, PATHINFO_EXTENSION);
$imageFileType = strtolower($imageFileType);
$valid_extionsions = array("jpg", "jpeg", "png");
$response = 0;
if (in_array($imageFileType, $valid_extionsions)) {
if (move_uploaded_file($_FILES['file']['tmp_name'], $location)) {
$response = $location; // this is to return the file path after upload
}
}
echo $response;
exit;
}
}
add_action("wp_ajax_upload_image", "upload_image");
add_action("wp_ajax_nopriv_upload_image", "upload_image");
Please note to add wp_ajax
and wp_ajax_nopriv
instead or wp_admin
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With