Here is a slightly tricky situation:
I am using ajax to call a function that uses FFMpeg to convert a video.
The code all works fine EXCEPT:
The execution is cut short so I end up with a video of 2 frames.
I assume this is ajax causing the problem because as far as its concerned, its called the function and returned a success output to my php page.
In other words, the ffmpeg script cuts off when the ajax has completed.
Is there a way I can tell ajax to wait for the ffmpeg function to finish or do i need to set up a cron job for it to run in the background?
EDIT:
Heres the code:
AJAX:
// watermark($thevideo)
var ajaxurl = "<?php echo admin_url('admin-ajax.php'); ?>";
var formData = new FormData();
formData.append('thevideo', thevideo);
formData.append('action', "watermark");
$.ajax({
url: ajaxurl,
type: "POST",
data:formData,cache: false,
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success:function(data) {
alert(data);
}
});
PHP FFMPEG Function:
// Watermark ***************
// IMPORTANT!
// This action & function can be called by ajax but requires absolute file paths!
add_action( 'wp_ajax_watermark', 'do_watermark' );
add_action( 'wp_ajax_nopriv_watermark', 'do_watermark' );
function getabspath( $file_url ){
return realpath($_SERVER['DOCUMENT_ROOT'] . parse_url( $file_url, PHP_URL_PATH ));
}
function do_watermark() {
session_start();
ini_set('display_errors', 1);
error_reporting(E_ALL);
// $thevideo = $_POST['thevideo'];
$thevideo = getabspath($_POST['thevideo']);
$newvideo = getabspath('./wp-content/uploads') . '/test.mp4';
$thewatermark = getabspath('./wp-content/uploads/mefbpic.png');
// For some reason we have to OMIT THE DRIVE LETTER from the watermark image path
// AND the backslashes need to be turned forward even tho its an absolute path!?!
$thewatermark = substr($thewatermark,2); // Cuts off the first 2 chars. - (C:)
$thewatermark = str_replace('\\','/',$thewatermark);
// require_once('./vendor/autoload.php');
require_once(getabspath('./vendor/autoload.php'));
$ffmpeg = FFMpeg\FFMpeg::create(array(
'ffmpeg.binaries' => getabspath('./FFMpeg/bin/ffmpeg.exe'),
'ffprobe.binaries' => getabspath('./FFMpeg/bin/ffprobe.exe'),
'timeout' => 3600, // The timeout for the underlying process
'ffmpeg.threads' => 12, // The number of threads that FFMpeg should use
));
$video = $ffmpeg->open($thevideo);
$video
->filters()
->resize(new \FFMpeg\Coordinate\Dimension(640, 360))
->watermark($thewatermark, [
'position' => 'relative',
'bottom' => 50,
'right' => 50,
])
->synchronize();
//$video
// ->save(new \FFMpeg\Format\Video\X264(), $thevideo);
$format = new \FFMpeg\Format\Video\X264();
$format->setAdditionalParameters(array('-y'));
$video->save($format, $newvideo);
echo 'done!';
}
Fixed it!
Just had to add
async: false,
to the ajax request!
Cheers ;)
Related
code at controller side is given below
try {
$this->load->library('m_pdf');
$querytype = "advance_search";
$showdata = [];
$pdfFilePath = utf8_decode("download_pdf.pdf");
ob_start();
$body= $this->load->view('result/pdf_generation', $this->common_advance_search($querytype),false); //here i am loading view for pdf
$this->m_pdf->pdf->WriteHTML($body);
$this->m_pdf->pdf->Output(FCPATH.$pdfFilePath,'F');// till here i can see the data in view
$result = ob_get_clean();
$response = array(
'op' => 'ok',
'file' => "data:application/pdf;base64,".base64_encode($result)
);
die(json_encode($response));
}
catch(\Mpdf\MpdfException $e) {
echo $e->getMessage();
}
Ajax Code
$.ajax({
url : "<?php echo base_url(); ?>"+scr,
method:"POST",
data:formData,
contentType: false,
cache: false,
processData:false,
dataType:'json'
}).done(function(data){ // here i am able to download the pdf in the browser
var $a = $("<a>");
$a.attr("href",data.file);
$("body").append($a);
$a.attr("download","file."+ext);
$a[0].click();
$a.remove();
});
result is given below
check result (screen shot added here)
with this code, it is giving me a currpted PDF file, i am able to get data and 'Export as pdf'. I have checked whether it is passing data from view, and yes it is doing so. But don't know what is the matter . I is printing everything outside it is working fine, Can anyone please let me know what should I do?
I am trying to change the picture when I submit ajax on success through changing the src of the img tag. I get this error though:
GET http://localhost:8000/%7B%7B%20asset('/uploads/images/$%7Bdata.picSource%7D')%7D%7D 404 (Not Found)
I also get errors in creating new buttons with jQuery that has twig path in their href atrributes. I have read the articles about putting the twig part in such quotes:"", but I use these: `` and inside of them "" in order to put variables freely in the path to make it dynamic.
This is my ajax query:
$(".uploadPic").on('submit', function(event){
event.preventDefault();
event.stopPropagation();
$.ajax({
type: "post",
url: "/upload",
data: new FormData($(".uploadPic")[0]),
processData: false,
contentType: false,
success: function (data) {
let newSource = `"{{ asset('/uploads/images/${data.picSource}')}}"`;
$("#userPic").attr('src', newSource);
},
error: function (response) {
console.log(response);
}
});
});
The response in the network tab is normal(the name and extension of the picture): {"picSource":"8bcfb2d2a1117cbb452f632829a5cad8.jpeg"}, but I get error from passing the new attribute.
The part from the controller on successfull ajax request:
if(isset($request->request)) {
$file = $request->files->get('user_pic_type')['userPic'];
$file = $user->getUserPic();
$fileName = $this->generateUniqueFileName() . '.' . $file->guessExtension();
$file->move(
$this->getParameter('users_directory'),
$fileName
);
$user->setUserPic($fileName);
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return new JsonResponse(array('picSource' => $fileName));
}
What I can do to correct this problem ?
You've mixed up JS (which runs in your browser) and PHP (which runs on your server and transmits rendered HTML to the browser). If you want to generate such an asset rule in the frontend, you should either fire an AJAX call for it or generate the URL by hand.
But as you already use an AJAX call, you should use it to return the image path for you. Add some code like this to your PHP controller:
/** #var \Symfony\Component\Asset\Packages $manager */
$manager = $this->get('assets.packages');
$imagePath = $manager->getUrl('/uploads/images/' . $fileName);
return new JsonResponse(array('picSource' => $fileName, 'imagePath' => $imagePath));
Now, the backend already generates all neccessary data for you and sends it to the browser
I'm trying to write a method in a php class that will use ajax to execute a php function that will push a file back to the browser.
It seems like its trying to write the file to the modx log, getting a lot of binary garbage in there.
Here is the method:
public function pushDocuments($formdata){
$data = $formdata['formdata'];
$file = MODX_PROTECTED_STORAGE . $data['target'];
$file_name = basename($file);
if (file_exists($file)) {
header("Content-Disposition: attachment; filename=\"$file_name\"");
header("Content-Length: " . filesize($file));
header("Content-Type: application/octet-stream;");
readfile($file);
};
$output = array(
'status' => 'success',
'error_messages' => array(),
'success_messages' => array(),
);
$output = $this->modx->toJSON($output);
return $output;
}
and here is the jquery:
$('.btn-get-document').click(function(){
var target = $(this).attr('data-target');
var postdata = {"snippet":"DataSync", "function":"pushDocuments", "target": target}; // data object ~ not json!!
console.log('target = ' + target + postdata );
$.ajax({
type: "POST",
url: "processors/processor.ajax.generic/",
dataType : "json",
cache : false,
data: postdata, // posting object, not json
success: function(data){
if(data.status == 'success'){
console.log("SUCCESS status posting data");
}else if(data.status == 'error'){
console.log("error status posting data");
}
},
error: function(data){
console.log("FATAL: error posting data");
}
});
});
it's running through the scripts and giving a success in the console [because I am forcing success] but no file is prompted for download and the binary garbage shows up in the modx log
What am I doing wrong?
In order to download a file, you'd have to use JS to redirect to the file's location. You can't pull the file contents through AJAX and direct the browser to save those contents as a file.
You would need to structurally change your setup. For instance, your PHP script can verify the existence of the file to be downloaded, then send a link to JS in order to download the file. Something like this:
if ( file_exists( $file )) {
$success_message = array(
'file_url' => 'http://example.com/file/to/download.zip'
);
}
$output = array(
'status' => 'success',
'error_messages' => array(),
'success_messages' => $success_message
);
Then modify the "success" portion of your AJAX return like this:
success: function( data ) {
if ( data.status == 'success' ) {
location.href = data.success_messages.file_url;
} else if ( data.status == 'error' ) {
console.log( 'error status posting data' );
}
},
Since you're directing to a file, the browser window won't actually go anywhere, so long as the file's content-disposition is set to attachment. Typically this would happen if you directed to any file the browser didn't internally handle (like a ZIP file). If you want control over this so that it downloads all files (including things the browser may handle with plugins), you can direct to another PHP script that would send the appropriate headers and then send the file (similar to the way you're sending the headers and using readfile() in your example).
#sean-kimball,
You might want to extend MODX's class based processor instead:
https://github.com/modxcms/revolution/blob/master/core/model/modx/processors/browser/file/download.class.php
It does the download from any media source and also access checking if you want.
Its implementation on manager side is:
https://github.com/modxcms/revolution/blob/master/manager/assets/modext/widgets/system/modx.tree.directory.js#L553
Back to your case, these examples might bring you some ideas.
JS Example:
$.ajax({
type: "POST",
// read my note down below about connector file
url: "assets/components/mypackage/connectors/web.php",
dataType : "json",
cache : false,
data: {
action: 'mypath/to/processor/classfile'
}
success: function(data){
},
error: function(data){
console.log("FATAL: error posting data");
}
});
Processor example:
<?php
require_once MODX_CORE_PATH . 'model/modx/processors/browser/file/download.class.php';
class myDownloadProcessor extends modBrowserFileDownloadProcessor {
// override things in here
}
return 'myDownloadProcessor';
For this, I also suggest you to use MODX's index.php main file as the AJAX's connector so the $modx object in processor inherits the access permission as well.
http://www.virtudraft.com/blog/ajaxs-connector-file-using-modxs-main-index.php.html
I'm not sure if somebody asked this already, at least i cant find the answer so i'm wondering what i'm doing wrong with my script.
I'm trying to delete a cookie with a callback done by Jquery that calls a php script on the background, BUT, whatever i try i cannot get this to properly work (deleting the cookie).
I've checked the php website and even looked at the RFC 2109 memo to find out how browsers and php try to accomplish that the cookie will be deleted.
So, my question here is; How can this fail?
Edit: i don't get any error message, deleting the cookie manually works and creating the cookie with the same type of callback done by jquery does also work. It just doesn't get deleted when i try the same callback with jquery to run the PHP script in the background in order to delete the cookie.
Code for that JQ callback action:
$(document).ready(function() {
var alert = $('#Cmessage');
$(".delete").on('click', function(){
$.ajax({
url: 'http://www.oostpijl.nl/shop/offerte/deletecookie.php',
type: 'get', // form submit method get/post
dataType: 'json', // request type html/json/xml
beforeSend: function() {
alert.fadeOut();
},
success: function(result) {
if(result.error){
alert.html(result.html).fadeIn();
console.log(e)
}else{
alert.html(result.html).fadeIn();
}
}
});
});
});
PHP script:
<?php
include("_offertesettings.php");
if( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) ){
setcookie('offerte', '', time() - 3600, '/' , '.oostpijl.nl' );
setcookie('offerteC', '', time() - 3600, '/', '.oostpijl.nl' );
$result = array("error" => false, "html" => null);
$result["error"] = false;
$result["html"] = "<script type='text/javascript'>setTimeout(function() { window.location='" . $config["BURL"] . "'; }, 10);</script>";
} else {
$result["error"] = true;
$result["html"] = "<h3>Error; Neem contact op met de webmaster</h3>";
}
echo json_encode($result);
exit;
?>
Make sure you get inside your isset condition. You should test it by printing something as a test then exit.
if( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) ){
echo json_encode('test');
exit;
}
also make sure there is no error in your included file "_offertesettings.php". You can check if there are PHP errors by adding those lines at the top of your PHP script.
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
to delete your cookies you just need this:
setcookie('offerte', '', time() - 3600);
setcookie('offerteC', '', time() - 3600);
I am trying to capture a highcharts chart and POST it to a PHP file
(result.php). I am able to capture image right now but I do not know how to POST captured image to another file. so far I have this code which is returning a PNG image
function postChart(chart) {
var obj = {},chart;
obj.svg = chart.getSVG();
obj.type = 'image/png';
obj.async = true;
exportUrl = 'http://export.highcharts.com/';
$.ajax({
type: "POST",
url: exportUrl,
data: obj,
cache:false,
async:true,
crossDomain:true,
success: function (data) {
// How to Send Image to result.php
},
error: function(data) {
}
});
}
and this result.php file as:
<?php
$content = $_POST['Not Sure What!'];
echo $content;
Now can you please let me know what can I put in
success: function (data) {
// How to Send Result to another Page
},
to post the image to result.php and how should I modify the result.php. Thanks
You can just use the highchart's exportChart API Like
function postChart(chart) {
chart.exportChart({
url : 'path/to/result.php',
type: 'image/png',
filename: 'my-chart'
});
}
Then from result.php you will be able to access the $_POST variable. which will contain following array, where $_POST['svg'] is the image in svg format.
array (
'filename' => 'my-chart',
'type' => 'image/png',
'width' => '0',
'scale' => '2',
'svg' => '',
)
You can then use the highchart's server side script to convert the image from svg to your desired format.
If you do not like to use java library for the conversion, you can also try this
Happy Coding!!
This works only if your php-script is somewhere on http://export.highcharts.com/
(Because you set the crossDomain property to true)
In your ajax method:
Change:
data: obj,
TO:
data: {
objName: obj,
}
Then in the result.php:
<?php
var_dump($_FILES['objName']);
// If you're interested, what else is inside $_FILES
var_dump($_FILES);
Not entirely sure what you're asking. This may be of some help though.
When working with files on upload use $_FILES. Its exactly like $_POST but for files.
Theres a selection of variables you can gather from the file using $_FILES.
<?
$tempname = $_FILES['file']['tmp_name'];
$filetype = $_FILES["file"]["type"];
$filesize = $_FILES['file']['size'];
?>
In the case above this references the file with a name of "file".