I am running in a Windows10 environment. My php script writes a pdf file and I simply want to have the file open up in the pdf viewer that I specify. I am using the "runAsynchronously" function given in the PHP manual and I have tried many variations. I have no problem getting the process to run in the background - it appears every time in my TaskManager process listing, but no window appears - what am I doing wrong? If I double click the link file that has been written it works fine. It is nothing to do with the path to the executable or the filename - I can replace the pdf viewer with "notepad.exe" and the $file with a suitable text file - the same thing happens, notepad appears as a process, but not as a window, and the link works fine.
Here are some code snippets
$cmd = "C:\\Program Files (x86)\\SumatraPDF\\SumatraPDF.exe";
runAsynchronously($cmd, $file, 7, null, true);
function runAsynchronously($path, $arguments, $windowstyle=1, $lnkfile=null, $exec=true) {
$tmp = (is_null($lnkfile)) ? 'C:\temp\temp.lnk' : $lnkfile;
try {
if(file_exists($tmp)) { unlink($tmp); }
$WshShell = new COM("WScript.Shell");
$oShellLink = $WshShell->CreateShortcut($tmp);
$oShellLink->TargetPath = $path;
$oShellLink->Arguments = $arguments;
$oShellLink->WorkingDirectory = dirname($path);
$oShellLink->WindowStyle = 1;
$oShellLink->Save();
$waitforcompletion = false;
if($exec) {
// Run kicks off the process in the background, but no window gets opened
$oExec = $WshShell->Run($tmp, $windowstyle, $waitforcompletion);
unlink($tmp);
} // if not executed link is left available for manual running
unset($WshShell,$oShellLink,$oExec);
} catch(Exception $ex) {
print $ex->getMessage();
}
}
If opening in the browser a pdf or downloading it solves your problem, try a class called PDFMerger:
https://github.com/clegginabox/pdf-merger
It uses an API called setasign FPDI and FPDF (https://packagist.org/packages/setasign/fpdi-fpdf#p-456)
I tested it here, because it also interested me and worked ok. (Wamp in Windows 8.1)
I put everything together(classes and folders of fpdi and fpdf) in a folder called pdfmerger because I was having some difficulty with namespaces and my code worked ok, but I know this is not the best way to include the classes - the example in GitHub page must help if you have problems with classes not finding classes):
<?php
include "pdfmerger/fpdf.php";
include "pdfmerger/fpdi.php";
include 'pdfmerger/PDFMerger.php';
$pdf = new PDFMerger();
//generate a pdf with the pages 1,2 and 3 and send to browser
$pdf->addPDF('originalpdfsavedintheserver.pdf', '1,2,3')
->merge('browser', 'nameinbrowser.pdf');
// REPLACE 'browser' WITH 'file', 'download', 'string', or 'browser' for output options
If you use the option 'download' you can choose the program that will open the pdf file in your windows settings(Choose default program to open pdfs):
https://www.cnet.com/how-to/how-to-set-default-programs-in-windows-10/
Related
I am using pdfparser for copy text from PDF files but some PDF files are copy protected or have different fonts so that pdfparser not working for that, is it possible to get text from copy protected PDF?
This is my Code :
// Include Composer autoloader if not already done.
error_reporting(E_ALL);
ini_set('display_errors', 1);
include 'vendor/autoload.php';
// Parse pdf file and build necessary objects.
$parser = new \Smalot\PdfParser\Parser();
$pdf = $parser->parseFile('tests.pdf');
// Retrieve all pages from the pdf file.
$pages = $pdf->getPages();
// Loop over each page to extract text.
foreach ($pages as $page) {
echo utf8_encode($page->getText());
}
?>
After trying this code I am not getting any error or warning. This code is only showing blank space. I have also try utf-8 encoding but still it is not working?
If the author of the PDF specified the Permissions flags of the document to not permit Copying or Extracting Text and Graphics then you should consider that. Not all PDF software respects such restrictions however.
\Smalot\PdfParser can't extract password protected files.
I've found a far better solution for that (providing your PHP service is running on a Linux server): use the command line tool “pdftotext” (included in the “poppler” package in, for example, Debian or Ubuntu).
It perfectly handles password protected files (it has an option to give password if required).
Used with something like this, inside a PHP script under web server on a Linux server, with a PDF file submitted through a web form:
// $filepath is the full file path properly extracted from the $_FILES variable
// after form submission.
// Expected running under Linux+Apache+PHP; if not, you may have to find your way.
if (! file_exists($filepath)) {
// In case systemd private temporary directory feature is active.
$filepath = '/proc/'.posix_getppid().'/root'.$filepath;
}
$cwdt = 4; // may be better fine tuned for better column alignment
// “sudo” is necessary mostly with systemd private temporary directory
// feature. Needs proper sudoers configuration, of course.
$cmd = "sudo /usr/bin/pdftotext -nopgbrk -fixed {$cwdt} {$filepath} -";
exec($cmd, $output, $res);
print_r($output);
I don't know if it is an answer to the “or having different fonts” requirement, however.
I have a .txt file located under some folder of my data files. Now I have created a long polling system (actually copied the code ) which is run by ajax.
Now the problem is that my php script is unable to fetch file modification time of the text file (it totally disregards the file).
Below I have both the original code of the author and my twerked code. The one of the author worked fine, but not mine.
Plz help.
The apache server is hosted on windows server
THe file path is absolutly correct and file exist.
Here's the section of my code which has error
while (true) {
//**The error occurs here**
$fileModifyTime = filectime($file);
if ($fileModifyTime === false) {
throw new Exception('Could not read last modification time');
}
// if the last modification time of the file is greater than the last update sent to the browser...
if ($fileModifyTime > $lastUpdate) {
setcookie('lastUpdate', $fileModifyTime);
require 'msgread.php';
// get file contents from last lines...
$fileRead = tailCustom($file, 8);
exit(json_encode([
'status' => true,
'time' => $fileModifyTime,
'content' => $fileRead
]));
}
// to clear cache
clearstatcache();
// to sleep
sleep(1);
}
here's the original code from where i copied
the author's original polling code
and here's my full code, just in case needed
My script which has error
I suspect that your problem is that file.txt does not exist. have you created it and ensured that it's in the current working directory of the script?
It's impossible to say more without seeing your actual code. If you select it and press Ctrl + K that will indent it all.
This question is asked before but non of the answers worked for me.
I use the following code to directly copy a file from a remote server to my server,
<?php
set_time_limit(0); //Unlimited max execution time
$remote_file_url = $_GET['url'];
$ext = pathinfo($remote_file_url, PATHINFO_EXTENSION);
$name = basename($remote_file_url);
if(isset($ext)){
$local_file = 'download/'.$name.'.'.$ext;
}
else
$local_file = 'download/'.$name;
$copy = copy( $remote_file_url, "1.mp4" );
if( !$copy ) {
echo "Doh! failed to copy $file...\n";
}
else{
echo "WOOT! success to copy $file...\n";
}
?>
It works well but it doesn't copy the files I get from Youtube. I use 1-Click Youtube Video Downloader extension for Firefox which gives me direct link to youtube videos. I can use these direct links in browser and Internet Download Manager as well.
For example the direct url of
https://www.youtube.com/watch?v=xPXrJwQ5lqQ
is
https://r6---sn-ab5l6nzy.googlevideo.com/videoplayback?ipbits=0&requiressl=yes&sparams=dur,ei,expire,id,initcwndbps,ip,ipbits,ipbypass,itag,lmt,mime,mip,mm,mn,ms,mv,pl,ratebypass,requiressl,source&ei=3DNOWfq4CImGc9rxvcgO&signature=3D188D073D872381433A45462E84928383D10D02.4E0AF7D777E76AA19A576D42983A81F4E62EF84D&lmt=1472135086539955&mime=video%2Fmp4&ratebypass=yes&id=o-ABaoUEn3pBt5SLXdWXlrzCdteMLfLPizrRTPoakDoLSX&expire=1498318908&source=youtube&dur=119.211&itag=22&pl=20&ip=162.217.31.128&key=cms1&redirect_counter=1&req_id=ce038b9993a9a3ee&cms_redirect=yes&ipbypass=yes&mip=159.203.89.210&mm=31&mn=sn-ab5l6nzy&ms=au&mt=1498297234&mv=m
The problem is my code can't copy this file to my server. I would like to know of there is any way to resolve such urls?
The error is
failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden in /home/...
thanks in advance.
Well, I have no idea why that happened. (Would it be expired?I hope not) I just managed to try another link for the above video (copy the link using right click) in your code as the $remote_file_url and it worked as expected
How did I get that link?
I've used the underlined library : YouTube-Downloader to the 1-Click Youtube Video Downloader extension (it is inherently used by that extension ) this way you will have more control over the process. Then after hosting the files in your web server. Simply run the index.php and when you use it, you'll get something like :
Then you can automate this last part to suit your needs.
That doesn't mean that all videos could be smoothly downloaded with this method. Because of the used videos that have signatures issue or that are recently uploaded issue and here's the list of issues of Youtube-Downloader
For that There is a fix that is somewhat involved: youtube-dl-php, it is based on a sound principle : there is a very good command line utility to download YouTube videos called youtube-dl : here is the download page
Basically, you'll just call it using php. Then, notice that you'll need its path installed in order for the following to work
After you install Composer, go to your web project folder
and run composer require norkunas/youtube-dl-php as explained in the Github page
When running its example, I've get an error
proc_open() 267 CreateProcess failed
I've never dealt with Symphony before and I've found it particularly interesting to play with YoutubeDl.php and redefine the $arguments passed to createProcess and commenting out much of the less useful configuration options to get rid of that error, give it more time to run with
ini_set('max_execution_time', 300);
And yikes it was downloaded.
You don't have to follow this unless you couldn't figure out a better way. It is just supposed to give you an idea of where lies the problem if you havn'et figure it out. And if you have that problem in the first place.
private function createProcess(array $arguments = [])
{
array_unshift($arguments, $this->binPath ?: 'youtube-dl');
$process = new Process("youtube-dl https://www.youtube.com/watch?v=nDMwW41AlSI");
/*$process->setEnv(['LANG' => 'en_US.UTF-8']);
$process->setTimeout($this->timeout);
$process->setOptions($this->processOptions);
if ($this->moveWithPhp) {
$cwd = sys_get_temp_dir();
} else {
$cwd = $this->downloadPath ?: sys_get_temp_dir();
}
$process->setWorkingDirectory($cwd);*/
return $process;
}
Or you can just write your own code that calls youtube-dl, good luck!
I am using a PHP COM Object to Open a Word 2013 file and count pages. My code works great for .docx files but not for .docm files. I am using php 5.4 and IIS 7.5 in a Windows 2008 R2 environment. Any recommendations?
// Create an instance of the Word application
$word = new COM("word.application");
if ($word) {
// Open the document
$word->Documents->Open($file_dir . $filename);
// Get the page count
$pagecount = $word->Documents[1]->ComputeStatistics(2);
}
You could try to turn off all macros like this before opening a file, this also disable security prompts:
$word->AutomationSecurity = 3; // disable all macros in the documents being opened
Well, doesn't .docm signify that there are macros or event macros present in the file?
Usually when the user opens a .docm file, the user is given a security prompt. Being that you are running under PHP, you might be running under a service and the prompt is not being seen in the hidden desktop, or security it preventing it from running at all. I would suggest you write some VBS code to try and open the same file under a console and see what the results are. If you get prompts or its being prevented, hopefully you will get better error messages.
var word
set word = CreateObject("Word.Application")
word.documents.open("path to my file")
var pageCount
pageCount = word.Documents(1).ComputeStatistics(s)
My PHP/MySQL web application has a function that combines a set of images for each user into a single PDF using ImageMagick. Each PDF is then placed into a ZIP file. Each image can be up to 5 MB in size. My problem is that the browser times out before the user can download the document.
Any ideas on how to best do this?
I was thinking I could create the ZIP file without sending it to the browser (i.e. remove the "headers" at the end of my code) and then email a link to the file; however, it still requires that the user wait a long time for the ZIP file to be created (it appears as if the browser is just hanging). Could this be done with AJAX behind the scenes or directly on the server somehow?
$tmp_path = sys_get_temp_dir().'/';
$archive_name = "myarchive.zip";
$zip = new ZipArchive();
if($zip->open($archive_name,1 ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
foreach ($rows AS $row) {
$irows = get_images($row['user_id']);
$images = array();
foreach($irows AS $irow){
$doc = fetch_document_path($irow['id']);
$output_file_name = $tmp_path.$irow['id'].'.jpg';
exec ('convert '.$doc.' '.$output_file_name);
$images[] = $irow['id'].'.jpg';
}
$images = implode(' ', $images);
$output_file_name = $tmp_path.$row['name'].'.pdf';
exec ('convert '.$images.' "'.$output_file_name.'"');
$zip->addFile($output_file_name,basename($output_file_name));
}
$zip->close();
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="output.zip"');
readfile($archive_name);
IMO you should run some background task that will do the job. Background worker can for example save URL to result file in DB after it'll finished (can also save some more information like current status and job progress), meantime webpage can periodically ask server using AJAX if job is already done or not and finally display link when it'll be available.
Simplest way to achieve that is to run your script as background process:
$arg1 = escapeshellarg($somearg1);
$arg2 = escapeshellarg($somearg1);
exec(sprintf('/usr/bin/php archiver.php %s %s > /dev/null 2>&1 & echo $!', $arg1, $arg2));
archiver.php should begin with following lines:
<?php
ignore_user_abort(true);
set_time_limit(0);
it'll prevent script from being stopped when parent script will finish working.
Second idea I have is more complex - you can write a daemon that will run in background waiting for jobs. To communicate with it you can use queues (like AMQP) or just database. With daemon you'll have more control on what is happening and when - in first approach it can happen that your application will fire too many processes.