I've made a script which uses $.ajax and FormData to pass two form objects to PHP. One form object is a text and the other is a file.
It worked well as a stand-alone script. However, after I added it to Wordpress, as a plugin, it keeps giving me "Uncaught TypeError: Illegal invocation".
I can't afford to serialize the formdata, simply because then I won't be able to pass the file to the callback function in PHP.
JS involving FormData before ajax call:
var fd = new FormData();
var file = jQuery(this).find('input[type="file"]');
var caption = jQuery(this).find('input[name=img_caption]');
var individual_file = file[0].files[0];
fd.append("file", individual_file);
var individual_capt = caption.val();
fd.append("caption", individual_capt);
This part above is 100% correct.
Ajax call:
jQuery.ajax({
type: 'POST',
url: fiuajax.ajaxurl,
data: {
action: 'fiu_upload_file',
security: fiuajax.security,
data: fd,
contentType: false,
processData: false,
},
success: function(response){
var dataObj = jQuery.parseJSON(response);
if(dataObj.message == 'error') {
jQuery('.fiu_validation').html('The following error occured: '+dataObj.desc);
}
else if(dataObj.message == 'success') {
jQuery('.fiu_file').val('');
}
console.log(response);
}
});
This is incredibly frustrating since it worked perfectly fine outside of Wordpress. I've tried de-registering Wordpress' jQuery and enqueueing the latest jQuery version, but it made no difference.
To recap:
1) Ajax/jQuery is refusing to pass a form object to PHP
2) Can't serialize the object because I need to preserve the file object
3) Script works outside of Wordpress
4) Tried updating to the newest jQuery version, no change
try this :
jQuery(document).on('click', '#submit', function(e){
e.preventDefault();
var fd = new FormData();
var file = jQuery(document).find('input[type="file"]');
var caption = jQuery(this).find('input[name=img_caption]');
var individual_file = file[0].files[0];
fd.append("file", individual_file);
var individual_capt = caption.val();
fd.append("caption", individual_capt);
fd.append('action', 'fiu_upload_file');
jQuery.ajax({
type: 'POST',
url: fiuajax.ajaxurl,
data: fd,
contentType: false,
processData: false,
success: function(response){
console.log(response);
}
});
});
php
function fiu_upload_file(){
var_dump($_FILES);
exit();
}
add_action('wp_ajax_fiu_upload_file', 'fiu_upload_file');
add_action('wp_ajax_nopriv_fiu_upload_file', 'fiu_upload_file');
I managed to do it. The code works on the latest version of Wordpress (4.9.4)
First of all, I'm using XMLHttpRequest to send the data and not the jQuery ajax. This means that you can adapt it to just pure JS.
Notice the xhttp.setRequestHeader("enctype","multipart/form-data"); which was essential to pass the FormData using this method.
JS:
var user_id = $('#user_id').val();
var picture = $('#userPic')[0].files[0];
console.log(picture);
if( picture && typeof picture !== undefined ) {
if ( picture['size'] > 1000000 ) {
alert('The Profile Pic can\'t be larger than 1Mb.');
return;
}
if ( picture['type'].indexOf('image') == -1 ) {
alert('The uploaded file needs to be an image.');
return;
}
var data = new FormData();
data.append('user_id', user_id);
data.append('userPic', picture);
// console.log(data);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log('Receive:' + this.responseText);
}
};
xhttp.open("POST", location.origin + "/wp-content/themes/search-and-go-child/ajax/upload_user_profile_pic_ajax.php", true);
xhttp.setRequestHeader("enctype","multipart/form-data");
xhttp.send(data);
}
The PHP part is also extremely useful since it requires the files needed to manipulate the received data with the WP core functions.
Here you will also find the code to upload an attachment using the WP core functions.
PHP:
// error_reporting(-1);
// ini_set('display_errors', 'On');
$path = $_SERVER['DOCUMENT_ROOT'];
require_once($path.'/wp-load.php');
require_once( '/home/s24t06b21lk5/public_html/wp-includes/template-loader.php' );
// require_once("/home/s24t06b21lk5/public_html/wp-admin" . '/includes/image.php');
require_once("/home/s24t06b21lk5/public_html/wp-admin" . '/includes/file.php');
// require_once("/home/s24t06b21lk5/public_html/wp-admin" . '/includes/media.php');
$user_id = $_POST['user_id'];
$picture = $_FILES['userPic'];
var_dump($user_id);
var_dump($picture);
$response = array();
if( isset($picture['name']) && $picture['name'] ) {
// Get the path to the upload directory.
$wp_upload_dir = wp_upload_dir();
$picture['name'] = preg_replace( '/[^0-9a-zA-Z.]/', '', basename( $picture['name'] ) );
// Upload the file
$upload_overrides = array( 'test_form' => false );
$upload_result = wp_handle_upload($picture, $upload_overrides);
// echo '<pre>'; print_r($upload_result); echo '</pre>' ;
if( $upload_result['url'] ) {
// Prepare an array of post data for the attachment.
$attachment = array(
'guid' => $upload_result['url'],
'post_mime_type' => $picture['type'],
'post_title' => $picture['name'],
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $upload_result['file'] );
if( $attach_id ) {
// Make sure that this file is included, as wp_generate_attachment_metadata() depends on it.
require_once( ABSPATH . 'wp-admin/includes/image.php' );
// Generate the metadata for the attachment, and update the database record.
$attach_data = wp_generate_attachment_metadata( $attach_id, $upload_result['file'] );
wp_update_attachment_metadata( $attach_id, $attach_data );
// Update the usermeta table with the uploaded avatar
if( !update_user_meta($user_id, 'wp_user_avatar', $attach_id ) || !update_user_meta($user_id, 'wp_zfgrf5v7rw_user_avatar', $attach_id) ) {
$response['result'] = FALSE;
$response['message'] = "The uploaded image could not be associated with the User ID in the database.";
}
else {
$response['result'] = TRUE;
}
}
else {
$response['result'] = FALSE;
$response['message'] = "Wordpress attachment post for the user's image could not created.";
}
}
else {
$response['result'] = FALSE;
$response['message'] = "The file couldn't be uploaded. Check the permissions.";
}
}
die( json_encode($response) );
Thank you.
Works whith any input(one or many simple or multiple), textarea, select in your form (WP 5.0.3)
$('#form').submit(function(e) {
e.preventDefault();
var form = $(this);
var formdata = (window.FormData) ? new FormData(form[0]) : null;
var data = (formdata !== null) ? formdata : form.serialize();
formdata.append("action", "fiu_upload_file");
$.ajax({
type: 'POST',
url: fiuajax.ajaxurl,
contentType: false,
processData: false,
dataType: 'JSON',
status: 200,
data: formdata,
success: function(data){
if(data.error == 'true') {
$('.msg').html(data.true);
}
else {
$('.msg').html(data.false);
// your code if you want an action ...
};
}
});
});
and php for only the files
foreach ($_FILES as $file) :
if($file['error'] == UPLOAD_ERR_NO_FILE) :
continue;
endif;
$valid_ext = array( 'jpg' , 'jpeg' , 'png' , 'doc' , 'docx' , 'pdf' , 'xls' , 'xlsx');
$extension_upload = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if ( in_array($extension_upload,$valid_ext) ) :
$name_upload = uniqid() . $file['name'];
$url_insert = trailingslashit( plugin_dir_path( dirname( __FILE__ ) ) ) . 'uploads';
wp_mkdir_p($url_insert);
$name_insert = trailingslashit($url_insert) . $name_upload;
$action = move_uploaded_file($file['tmp_name'],$name_insert);
$msg_true = 'Upload ok ';
else :
$msg_error = 'Upload error';
endif;
endforeach;
$result = !isset($msg_error);
$msg = array();
if($result) :
$msg['error'] = 'true';
$msg['true'] = $msg_true;
else :
$msg['error'] = 'false';
$msg['false'] = $msg_error;
endif;
header('Content-Type: application/json');
echo json_encode($msg);
I added
dataType: 'json'
and it helps.
Full listing of your code of Ajax call:
jQuery.ajax({
type: 'POST',
url: fiuajax.ajaxurl,
data: {
action: 'fiu_upload_file',
security: fiuajax.security,
data: fd,
dataType: 'json',
contentType: false,
processData: false,
},
success: function(response){
var dataObj = jQuery.parseJSON(response);
if(dataObj.message == 'error') {
jQuery('.fiu_validation').html('The following error occured: '+dataObj.desc);
}
else if(dataObj.message == 'success') {
jQuery('.fiu_file').val('');
}
console.log(response);
}
});
here some modified code in case you have multiple data and multiple files
var fd = new FormData();
var data = jQuery('#yourformID').serializeArray();
jQuery.each(data,function(key,input){
fd.append(input.name,input.value);
});
var file = jQuery(document).find('input[type="file"]');
jQuery.each(jQuery(file), function(i, obj) {
jQuery.each(obj.files,function(j,file){
fd.append('files[' + j + ']', file);
})
});
fd.append('action', 'fiu_upload_file');
Related
I developed a PHP project, now I am working on connecting it to react native app. However, I tried many codes to upload image to the server nothing works.
Here is my code example,
const uploadImage = async () => {
// Check if any file is selected or not
if (singleFile != null) {
// If file selected then create FormData
const fileToUpload = singleFile;
const data = new FormData();
data.append('file_attachment', fileToUpload);
// Please change file upload URL
fetch(
'http://192.168.8.105/insaf/mobileConnection/upload.php',
{
method: 'post',
body: data,
headers: {
'Content-Type': 'multipart/form-data; ',
},
}
).then((response) => response.json())
.then((responseJson) => {
//Hide Loader
setLoading(false);
console.log(responseJson);
// If server response message same as Data Matched
if (responseJson[0].Message == "Success") {
navigation.replace('ReqPriceList');
} else {
//setErrortext(responseJson.msg);
console.log('Please check');
}
})
.catch((error) => {
//Hide Loader
setLoading(false);
console.error(error);
});
} else {
// If no file selected the show alert
alert('Please Select File first');
}
};
And for the PHP server side (upload.php), here is the code
if(!empty($_FILES['file_attachment']['name']))
{
$target_dir = "../assets/files/request/";
if (!file_exists($target_dir))
{
mkdir($target_dir, 0777);
}
$target_file =
$target_dir . basename($_FILES["file_attachment"]["name"]);
$imageFileType =
strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if file already exists
if (file_exists($target_file)) {
echo json_encode(
array(
"status" => 0,
"data" => array()
,"msg" => "Sorry, file already exists."
)
);
die();
}
// Check file size
if ($_FILES["file_attachment"]["size"] > 50000000) {
echo json_encode(
array(
"status" => 0,
"data" => array(),
"msg" => "Sorry, your file is too large."
)
);
die();
}
if (
move_uploaded_file(
$_FILES["file_attachment"]["tmp_name"], $target_file
)
) {
echo json_encode(
array(
"status" => 1,
"data" => array(),
"msg" => "The file " .
basename( $_FILES["file_attachment"]["name"]) .
" has been uploaded."));
} else {
echo json_encode(
array(
"status" => 0,
"data" => array(),
"msg" => "Sorry, there was an error uploading your file."
)
);
}
}
I got this code from here https://aboutreact.com/file-uploading-in-react-native/
And I am getting
this error
Can anyone help me?
Any alternative solution will be fine.
Edit:
based on #Sadia Chaudhary code this function works
let uploadImage = async () => {
//Check if any file is selected or not
if (singleFile != null) {
//If file selected then create FormData
const fileToUpload = singleFile;
console.log("fileToUpload is " + fileToUpload);
const uriPart = fileToUpload[0].uri;
const fileExtension = fileToUpload[0].name.split('.')[1];
console.log("fileExtension is " + fileExtension);
const data = new FormData();
//const uriPart = fileToUpload.split('.');
//const fileExtension = uriPart[uriPart.length - 1];
data.append('file_attachment', {
uri: uriPart,
name: `photo.${fileExtension}`,
type: `image/${fileExtension}`
});
let res = await fetch(
'http://myIp/insaf/mobileConnection/uploads.php',
{
method: 'post',
body: data,
headers: {
'Content-Type': 'multipart/form-data; ',
},
}
);
let responseJson = await res.json();
if (responseJson.status == 1) {
alert('Upload Successful');
}
} else {
//if no file selected the show alert
alert('Please Select File first');
}
};
The error has nothing to do with the image upload. You are facing this error because of response.json(). Also, try to convert image like this.
//retrive the file extension of your photo uri
const uriPart = imageSource.split('.');
const fileExtension = uriPart[uriPart.length - 1];
formData.append('photo', {
uri: imageSource,
name: `photo.${fileExtension}`,
type: `image/${fileExtension}`
});
I have code that sends an image to my server and everything works fine. However i am now truing to send a file to my server using an input tag in ionic However i cant seem to get it working.
I get an error from the php file saying undefined index 'file'
HTML
<ion-col>
<ion-label>Add a File</ion-label>
<ion-input type='file' [(ngModel)]="fileName"></ion-input>
</ion-col>
TS file
addFile() {
this.addService.addFile(this.fileName).subscribe(res => {
console.log(res);
});
}
service
addFile(file) {
let headers = new HttpHeaders();
// headers = headers.set('Content-Type', 'application/json');
headers = headers.set('Authorization', '' + this.token);
const formData = new FormData();
formData.append('file', file);
return this.http.post<any>('http://domain.fileUpload.php', formData, {headers});
}
PHP API
$target_path = "files/";
$target_path = $target_path . basename( $_FILES['file']['name']);
$findDate = date("Y-m-d");
if (move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) {
header('Content-type: application/json');
$data = ['success' => true, 'message' => 'Upload and move success'];
echo json_encode( $data );
} else {
header('Content-type: application/json');
$data = ['success' => false, 'message' => 'There was an error uploading the file (folder), please try again!'];
echo json_encode( $data );
}
uploadMethod
uploadFile: ''; // from ngModel
fileUpload(path) {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'file',
fileName: '.png',
chunkedMode: false,
};
console.log(this.uploadFile);
fileTransfer
.upload(this.uploadFile, 'http://domain/fileUpload.php',
options
)
.then(
data => {
console.log(data + 'Uploaded Successfully');
// console.log(JSON.parse(data.));
// let res = JSON.parse(data);
let res = data;
if (res['success']) {
console.log('True');
}
},
err => {
console.log(err);
}
);
}
Blow is the Example Code:
import { Platform } from 'ionic-angular';
checkPlatform: boolean = fasle;
constructor(public plt: Platform) {
if (this.plt.is('ios')) {
this.checkPlatform == true; // if platform ios this will be true
}
if (this.plt.is('android')) {
this.checkPlatform == true; // if platform androidthis will be true
}
}
imageUpload(path) {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'image',
fileName: '.png',
chunkedMode: false,
//mimeType: "image/jpeg",
}
fileTransfer.upload(path, 'https://yourDomain.com/api/imageUpload', options)
.then((data) => {
console.log(data+" Uploaded Successfully");
console.log(JSON.parse(data.response));
let res = JSON.parse(data.response);
if (res.success == true) {
// do whats ever you want to do
}
}, (err) => {
console.log(err);
});
}
Pass the cordova file path as parameter in this function.
inside you HTML template show buttons or input type like this:
<input type="file" *ngIf="checkPlatform == true">
if you see this you can notice allowed types are :
export type TextFieldTypes = 'date' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url' | 'time';
if you want to upload files follow this link i think you will find the answer
I check your code and as i see file added to FormData is filename with string Type, not File or Blob Data Type. So in this case it will not send file into $_FILES, it actually send its value to $_POST in your PHP Server. In summary, File and Blob Type will be sent to $_FILES, other data types will be sent to the appropriate global variables.
There is also a good example on how to validate your file in PHP Server: https://www.php.net/manual/en/features.file-upload.php
I'm trying to save an image returned from react-native-view-shot which looks something like this (file:///data/user/ReactNative-snapshot-image123.png) but I don't know why the image is not saved on my server.
This is what I've done.
savePicture = () =>{
this.refs.viewShot.capture().then(uri => {
this.setState(
{
imageURI:uri
});
var data = new FormData();
data.append('image', {
uri: this.state.imageURI,
name: 'my_photo.png',
type: 'image/png'
});
fetch('http://www.url.com/upload.php', {
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
method: 'POST',
body: JSON.stringify({
image: data
})
})
.then((response) => response.json())
.then((responseData) => {console.warn(responseData);})
.catch((error) => {
console.warn(error);
})
.done();
});
}
and here is my php to save the image on my server.
<?
header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Headers: *");
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$shuffledid = str_shuffle(124243543534543534);
$url = $shuffledid;
$path = $_SERVER['DOCUMENT_ROOT'].'/android';
$json = json_decode(file_get_contents('php://input'), true);
$img = $json['image'];
list($width,$height,$type) = getimagesize($img);
switch(strtolower(image_type_to_mime_type($type)))
{
case 'image/gif':
$pic = imagecreatefromgif($img);
break;
case 'image/png':
$pic = imagecreatefrompng($img);
break;
case 'image/jpeg':
$pic = imagecreatefromjpeg($img);
break;
default:
return false;
break;
}
$bg = imagecreatetruecolor(600,700);
imagecopyresampled($bg,$img,0,0,0,0,600,700,$width,$height);
imagepng($bg, $path.'/'.$url.'.png');
imagedestroy($img);
echo "done";
}
?>
My PHP just returns this error:
getimagesize() expects parameter 1 to be string, array given
I tried with var_dump($_POST) to see what is returned but I got something like this
{line:21352",column:16,sourceUrl:http.../index.delta?platform=android$dev=true...
Do you have any idea what I'm not doing right?
I've also did
body: data
on my react fetch without json.stringify but still nothing.
Thank you!
Solved! If someone needs this
const formData = new FormData();
formData.append('image', {
uri: this.state.imageURI,
name: 'my_photo.png',
type: 'image/png'
});
formData.append('Content-Type', 'image/png');
fetch('http://www.url.com/upload.php',{
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
})
.catch((error) => {
console.log(error);
});
});
PHP
$img = $_FILES['image']['tmp_name'];
$shuffledid = str_shuffle(124243543534543534);
$url = $shuffledid;
$path = $_SERVER['DOCUMENT_ROOT'].'/android';
list($width,$height,$type) = getimagesize($img);
$pic = imagecreatefrompng($img);
$bg = imagecreatetruecolor(600,700);
imagecopyresampled($bg,$pic,0,0,0,0,600,700,$width,$height);
imagepng($bg, $path.'/'.$url.'.png');
imagedestroy($pic);
echo json_encode("done");
thanks for taking a look at my question.
The Problem
I need to be able to an upload feature image(thumbnail) that is associated with a post, the website that is being worked on has the ability to make posts from the front-end of the website.
Custom code implemented
in the post submission form I'm using a input element of type file:
<form class="compose-post-form" method="POST" enctype="multipart/form-data">
...
<input type="file" name="featured" id="featured">
...
</form>
The data is being sent to the backend on form submit with jQuery AJAX:
$.ajax({
type: 'post',
url: t_ajax_url.ajax_url,
data: $this.serialize() + "&tri_post_content="+article_content+"&article="+article,
beforeSend: function () {
is_sending = true;
},
success: function (data) {
//window.location.replace(get_homepage_url+'trisine');
var fd = new FormData();
var file = $('#featured').val();
fd.append("featured", file);
fd.append('action', 'thumbnail_up');
jQuery.ajax({
type: 'POST',
url: t_ajax_url.ajax_url,
data: fd,
contentType: false,
processData: false,
success: function(response){
console.log(response);
}
});
},
error: function(xhr, status, error) {
console.log(status);
}
});
This is the code that saves the thumbnail, for now I'm just testing with a post ID of 22:
add_action( 'wp_ajax_thumbnail_up', 't_thumbnail_up' );
function t_thumbnail_up(){
$uploaddir = wp_upload_dir();
$file = $_FILE['featured'];
$uploadfile = $uploaddir['path'] . '/' . basename( $file['name'] );
move_uploaded_file( $file['tmp_name'] , $uploadfile );
$filename = basename( $uploadfile );
$wp_filetype = wp_check_filetype(basename($filename), null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', $filename),
'post_content' => '',
'post_status' => 'inherit',
'menu_order' => $_i + 1000
);
$attach_id = wp_insert_attachment( $attachment, $uploadfile );
update_post_meta(22, '_thumbnail_id',$attach_id);
set_post_thumbnail( 22, $thumbnail_id );
exit();
}
The results are that something get's uploaded but it seems to only be the folders name, which is November's month number, the folder isn't actually created on the server:
Any help on how I can get this to work will be highly appreciated.
Use this functions to handle files from ajax.
<?php
$thumbnail = $_FILES[ 'featured' ];
$thumbnail_id = media_handle_sideload( $thumbnail, $post_id );
set_post_thumbnail( $post_id, $screenshot_id );
I need to send the param imgName (together with the picture) to php in order to change the "image default name to imgName"
var imgName = "30";
file_data = $('#pictureInput').prop('files')[0];
form_data = new FormData();
form_data.append('file', file_data);
var newdata = {imgName: imgName, form_data: form_data};
var json = JSON.stringify(newdata);
$.ajax({
url: 'editImage.php',
cache: false,
contentType: false,
processData: false,
data: json,
type: 'post',
success: function(data){
console.log(data);
}
});
php
(i need help with my php)
move_uploaded_file($_FILES['file']['tmp_name'], 'pictures/' . $imgName . '.png');
Try as follows:-
$imgName = $_POST['imgName'];
move_uploaded_file($_FILES['file']['tmp_name'], 'pictures/' . $imgName . '.png');
$imgName = tempnam('/pictures', '');
unlink($imgName);
move_uploaded_file($_FILES['file']['tmp_name'], $imgName);
I think using tempnam() is good for you. You do not need to worry about randomness.
change your js code as
var formData = new FormData();
var imagefile = document.querySelector('#pictureInput');
if (imagefile.files && imagefile.files[0]) {
formData.append("file", imagefile.files[0]);
}
and in ajax
data: formData,