Generating JPG's from office files (.doc .ppt etc) using PHP - php

I'm building an application where people can upload files and share them with other people. Part of what we are looking to do is allow people to preview the file on-line.
Is there a strait forward way to generate a jpgs for the first X amount of pages from a document? We could then place these jpgs in the web page allowing the user to preview.
I have looked at installing open office on the server but was hoping there was a php library somewhere that does the same job.
Can anybody help?
Cheers
Btw, doesnt have to be jpg, any image file would be fine (actually even pdf would be ok)

Try this with com class:
You can use com class for convert office file to jpg
COM class Reference: -
http://us2.php.net/manual/en/class.com.php
or below code is convert ppt to jpg format
<html>
<head>
<title>ShotDev.Com Tutorial</title>
</head>
<body>
<?
$ppApp = new COM("PowerPoint.Application");
$ppApp->Visible = True;
$strPath = realpath(basename(getenv($_SERVER["SCRIPT_NAME"]))); // C:/AppServ/www/myphp
$ppName = "MySlides.ppt";
$FileName = "MyPP";
//*** Open Document ***//
$ppApp->Presentations->Open(realpath($ppName));
//*** Save Document ***//
$ppApp->ActivePresentation->SaveAs($strPath."/".$FileName,17); //'*** 18=PNG, 19=BMP **'
//$ppApp->ActivePresentation->SaveAs(realpath($FileName),17);
$ppApp->Quit;
$ppApp = null;
?>
PowerPoint Created to Folder <b><?=$FileName?></b>
</body>
</html>
---------------------------
Or try this :-
$powerpnt = new COM("powerpoint.application") or die("Unable to instantiate Powerpoint");
$presentation = $powerpnt->Presentations->Open(realpath($file), false, false, false) or die("Unable to open presentation");
foreach($presentation->Slides as $slide)
{
$slideName = "Slide_" . $slide->SlideNumber;
$exportFolder = realpath($uploadsFolder);
$slide->Export($exportFolder."\\".$slideName.".jpg", "jpg", "600", "400");
}
$powerpnt->quit();
?>
or convert word to jpg
<?php
// starting word
$word = new COM("word.application") or die("Unable to instantiate Word");
echo "Loaded Word, version {$word->Version}\n";
//bring it to front
$word->Visible = 1;
//open an empty document
$word->Documents->Add();
//do some weird stuff
$word->Selection->TypeText("This is a test...");
$word->Documents[1]->SaveAs("Useless test.doc");
//closing word
$word->Quit();
//free the object
$word = null;
?>

You cannot use Office Interop to automate such a task, see Microsoft reasons for that here:
https://support.microsoft.com/en-us/kb/257757
The best approach is to use a powerful library such as Aspose.Slides (compatibility with ppt, pptx, powerful manipulation) that are designed to be used as an API.
You can consume Aspose.Slides from PHP by means of the NetPhp library. There is an example here:
http://www.drupalonwindows.com/en/blog/powerpoint-presentation-images-php-drupal-example
The relevant piece of code is this one, it has some Drupal specific stuff, but you can see how it goes and make it work on other places:
protected function processFilePowerpoint(array $file, array &$files) {
/** #var \Drupal\wincachedrupal\NetPhp */
$netphp = \Drupal::service('netphp');
$runtime = $netphp->getRuntime();
$runtime->RegisterAssemblyFromFile("libraries/_bin/aspose/Aspose.Slides.dll", "Aspose.Slides");
$runtime->RegisterAssemblyFromFullQualifiedName("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing");
$destination = strtr(PresentacionSlide::UPLOAD_LOCATION, ['[envivo_presentacion:id]' => $this->entity->id()]);
file_prepare_directory($destination, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
$sourcefile = drupal_realpath($file['tmppath']);
$presentation = $runtime->TypeFromName("Aspose.Slides.Presentation")->Instantiate($sourcefile);
$format = $runtime->TypeFromName("System.Drawing.Imaging.ImageFormat")->Png;
$x = 0;
/** #var \NetPhp\Core\NetProxyCollection */
$slides = $presentation->Slides->AsIterator();
foreach ($slides as $slide) {
$x++;
$bitmap = $slide->GetThumbnail(1, 1);
$destinationfile = $destination . "\\slide_{$x}.png";
$bitmap->Save(drupal_realpath($destinationfile), $format);
$files[] = PresentacionSlide::fromFile($destinationfile);
}
$presentation->Dispose();
}

For a PHP-specific option you could use PHPWord - this library is written in PHP and provides classes to read from and write to different document file formats (including .doc and .docx), but it won't give you the ability to convert from the full range of Office files.
To convert any Office file on any platform you could use a file conversion API like Zamzar. It can convert from all Office formats (DOC / DOCX / PPT / PPTX / XLS / XLSX) into images (JPG, PNG, GIF etc) and PDF.
Code to call from PHP would be as follows (more info in the docs).
<?php
// Build request
$endpoint = "https://api.zamzar.com/v1/jobs";
$apiKey = "YOUR_KEY";
$sourceFilePath = "/tmp/my.doc"; // Or DOCX/PPT/PPTX/XLS/XLSX
$targetFormat = "jpg";
$sourceFile = curl_file_create($sourceFilePath);
$postData = array(
"source_file" => $sourceFile,
"target_format" => $targetFormat
);
// Send request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, $apiKey . ":");
$body = curl_exec($ch);
curl_close($ch);
// Process response (with link to converted files)
$response = json_decode($body, true);
print_r($response);
?>

Related

Creating a zip file on the fly from files stored on S3 using php

I have a Laravel web app in which users can upload files. These files can be sensitive and although they are stored on S3 they are only accessed via my webservers (streamed download). Once uploaded users may wish to download a selection of these files.
Previously when users went to download a selection of files my web server would download the files from S3, zip them locally and then send the zip down to the client. However once in production due to file sizes the server response would frequently time out.
As an alternative method I want to zip the files on the fly via ZipStream but I haven't had much luck. The zip file either ends up with corrupted files or is corrupted itself and incredibly small.
If it possible to pass a stream resource for a file on S3 to ZipStream and what is the best way to address my timeout issues?
I have tried several method my most recent two are as follows:
// First method using fopen
// Results in tiny corrupt zip files
if (!($fp = fopen("s3://{$bucket}/{$key}", 'r')))
{
die('Could not open stream for reading');
}
$zip->addFileFromPath($file->orginal_filename, "s3://{$bucket}/{$key}");
fclose($fp);
// Second method tried get download the file from s3 before sipping
// Results in a reasonable sized zip file that is corrupt
$contents = file_get_contents("s3://{$bucket}/{$key}");
$zip->addFile($file->orginal_filename, $contents);
Each of these sits within a loop that goes through each files. After the loop I call $zip->finish().
Note I do not get any php errors just corrupt files.
In the end the solution was to use signed S3 url's and curl to provide a file stream for ZipStream as demonstrated by s3 bucket steam zip php. The resulting code edited from the aforementioned source is as follows:
public function downloadZip()
{
// ...
$s3 = Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$client->registerStreamWrapper();
$expiry = "+10 minutes";
// Create a new zipstream object
$zip = new ZipStream($zipName . '.zip');
foreach($files as $file)
{
$filename = $file->original_filename;
// We need to use a command to get a request for the S3 object
// and then we can get the presigned URL.
$command = $client->getCommand('GetObject', [
'Bucket' => config('filesystems.disks.s3.bucket'),
'Key' => $file->path()
]);
$signedUrl = $request = $client->createPresignedRequest($command, $expiry)->getUri();
// We want to fetch the file to a file pointer so we create it here
// and create a curl request and store the response into the file
// pointer.
// After we've fetched the file we add the file to the zip file using
// the file pointer and then we close the curl request and the file
// pointer.
// Closing the file pointer removes the file.
$fp = tmpfile();
$ch = curl_init($signedUrl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
curl_close($ch);
$zip->addFileFromStream($filename, $fp);
fclose($fp);
}
$zip->finish();
}
Note this requires curl and php-curl to be installed and functioning on your server.
I had the same issues as #cubiclewar and investigated a little bit. I found that the most up to date solution to this doesn't need curl and it visible here on the wiki for the maennchen/ZipStream-PHP/ library.
https://github.com/maennchen/ZipStream-PHP/wiki/Symfony-example
use ZipStream;
//...
/**
* #Route("/zipstream", name="zipstream")
*/
public function zipStreamAction()
{
//sample test file on s3
$s3keys = array(
"ziptestfolder/file1.txt"
);
$s3Client = $this->get('app.amazon.s3'); //s3client service
$s3Client->registerStreamWrapper(); //required
//using StreamedResponse to wrap ZipStream functionality for files on AWS s3.
$response = new StreamedResponse(function() use($s3keys, $s3Client)
{
// Define suitable options for ZipStream Archive.
$opt = array(
'comment' => 'test zip file.',
'content_type' => 'application/octet-stream'
);
//initialise zipstream with output zip filename and options.
$zip = new ZipStream\ZipStream('test.zip', $opt);
//loop keys - useful for multiple files
foreach ($s3keys as $key) {
// Get the file name in S3 key so we can save it to the zip
//file using the same name.
$fileName = basename($key);
//concatenate s3path.
$bucket = 'bucketname'; //replace with your bucket name or get from parameters file.
$s3path = "s3://" . $bucket . "/" . $key;
//addFileFromStream
if ($streamRead = fopen($s3path, 'r')) {
$zip->addFileFromStream($fileName, $streamRead);
} else {
die('Could not open stream for reading');
}
}
$zip->finish();
});
return $response;
}

PHP: Get metadata of a remote .mp3 file

I am looking for a function that gets the metadata of a .mp3 file from a URL (NOT local .mp3 file on my server).
Also, I don't want to install http://php.net/manual/en/id3.installation.php or anything similar to my server.
I am looking for a standalone function.
Right now i am using this function:
<?php
function getfileinfo($remoteFile)
{
$url=$remoteFile;
$uuid=uniqid("designaeon_", true);
$file="../temp/".$uuid.".mp3";
$size=0;
$ch = curl_init($remoteFile);
//==============================Get Size==========================//
$contentLength = 'unknown';
$ch1 = curl_init($remoteFile);
curl_setopt($ch1, CURLOPT_NOBODY, true);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_HEADER, true);
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
$data = curl_exec($ch1);
curl_close($ch1);
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
$contentLength = (int)$matches[1];
$size=$contentLength;
}
//==============================Get Size==========================//
if (!$fp = fopen($file, "wb")) {
echo 'Error opening temp file for binary writing';
return false;
} else if (!$urlp = fopen($url, "r")) {
echo 'Error opening URL for reading';
return false;
}
try {
$to_get = 65536; // 64 KB
$chunk_size = 4096; // Haven't bothered to tune this, maybe other values would work better??
$got = 0; $data = null;
// Grab the first 64 KB of the file
while(!feof($urlp) && $got < $to_get) { $data = $data . fgets($urlp, $chunk_size); $got += $chunk_size; } fwrite($fp, $data); // Grab the last 64 KB of the file, if we know how big it is. if ($size > 0) {
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RESUME_FROM, $size - $to_get);
curl_exec($ch);
// Now $fp should be the first and last 64KB of the file!!
#fclose($fp);
#fclose($urlp);
} catch (Exception $e) {
#fclose($fp);
#fclose($urlp);
echo 'Error transfering file using fopen and cURL !!';
return false;
}
$getID3 = new getID3;
$filename=$file;
$ThisFileInfo = $getID3->analyze($filename);
getid3_lib::CopyTagsToComments($ThisFileInfo);
unlink($file);
return $ThisFileInfo;
}
?>
This function downloads 64KB from a URL of an .mp3 file, then returns the array with the metadata by using getID3 function (which works on local .mp3 files only) and then deletes the 64KB's previously downloaded.
Problem with this function is that it is way too slow from its nature (downloads 64KB's per .mp3, imagine 1000 mp3 files.)
To make my question clear : I need a fast standalone function that reads metadata of a remote URL .mp3 file.
This function downloads 64KB from a URL of an .mp3 file, then returns the array with the metadata by using getID3 function (which works on local .mp3 files only) and then deletes the 64KB's previously downloaded. Problem with this function is that it is way too slow from its nature (downloads 64KB's per .mp3, imagine 1000 mp3 files.)
Yeah, well what do you propose? How do you expect to get data if you don't get data? There is no way to have a generic remote HTTP server send you that ID3 data. Really, there is no magic. Think about it.
What you're doing now is already pretty solid, except that it doesn't handle all versions of ID3 and won't work for files with more than 64KB of ID3 tags. What I would do to improve it to is to use multi-cURL.
There are several PHP classes available that make this easier:
https://github.com/jmathai/php-multi-curl
$mc = EpiCurl::getInstance();
$results[] = $mc->addUrl(/* Your stream URL here /*); // Run this in a loop, 10 at a time or so
foreach ($results as $result) {
// Do something with the data.
}

Download file from google drive api to my server using php

1 - I have configure google picker and it is working fine and I select the file from picker and get the file id.
2 - After refresh token etc all process I get the file metadata and get the file export link
$downloadExpLink = $file->getExportLinks();
$downloadUrl = $downloadExpLink['application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
3 - After that I use this
if ($downloadUrl) {
$request = new Google_HttpRequest($downloadUrl, 'GET', null, null);
$httpRequest = Google_Client::$io->authenticatedRequest($request);
if ($httpRequest->getResponseHttpCode() == 200)
{
$content = $httpRequest->getResponseBody();
print_r($content);
} else {
// An error occurred.
return null;
}
and get this response
[responseBody:protected] => PK��DdocProps/app.xml���
�0D���k�I[ѫ��m
��!����A={���}�
2G�Z�g�V��Bľ֧�n�Ҋ�ap!����fb�d����k}Ikc�_`t<+�(�NJ̽�����#��EU-
�0#���P����........
4 - I use some cURL functions to get file from google drive and save it to server. IN server directory a file created but cropped. I use this code
$downloadExpLink = $file->getExportLinks();
$downloadUrl = $downloadExpLink['application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
//$downloadUrl value is
/*https://docs.google.com/feeds/download/documents/export/Export?id=1CEt1ya5kKLtgK************IJjDEY5BdfaGI&exportFormat=docx*/
When I put this url into browser it will download file successfully but when I use this url to fetch file with cURL or any php code and try to save it on server it saves corrupted file.
$ch = curl_init();
$source = $downloadUrl;
curl_setopt($ch, CURLOPT_URL, $source);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec ($ch);
curl_close ($ch);
$destination = "test/afile5.docx";
$file = fopen($destination, "w+");
fputs($file, $data);
fclose($file);
It result a corrupted file stored on server but whe I use this code to get any file other then google drive I download it successfully on server.
Can any one please help that how to download file from $downloadUrl to my server using php ?

add file to $_FILES array by reading remote file

I'm pretty new to php and we're trying to write a plugin for wordpress. We have a server with images on it and we'd like to have the plugin have a list of images to download from the server. It then needs to go through that list and read each image from the server into the $_FILES variable that we can then pass to the wordpress media_handle_upload function.
I've been able to read a remote file with the following code. But I'm not sure where to go from here.
$url = 'http://www.planet-source-code.com/vb/2010Redesign/images/LangugeHomePages/PHP.png';
$img = curl_init();
curl_setopt($img, CURLOPT_URL, $url);
curl_setopt($img, CURLOPT_HEADER, 1);
curl_setopt($img, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($img, CURLOPT_BINARYTRANSFER, 1);
$file = curl_exec($img);
curl_close($img);
$file_array = explode("\n\r", $file, 2);
$header_array = explode("\n", $file_array[0]);
foreach($header_array as $header_value) {
$header_pieces = explode(':', $header_value);
if(count($header_pieces) == 2) {
$headers[$header_pieces[0]] = trim($header_pieces[1]);
}
}
header('Content-type: ' . $headers['Content-Type']);
header('Content-Disposition: ' . $headers['Content-Disposition']);
$imgFile = substr($file_array[1], 1);
echo $imgFile;
Solution: Lookup table
Create images name list or image file path(link) list as json,xml or txt format. so it will act like as lookup table. it can be parse easily (just like RSS feed customization). call the json or xml file and get the data in the form of array. now you can process it easily

Convert image to pdf php

I am using csxi to make scanning for documnets as image, but I have to upload pdf files to server. How can I convert image to PDF in php ? or is there any way to make csxi scan documents as PDF not image
If you have ImageMagick installed on your machine you could use the ImageMagick bindings for PHP to execute some simple PHP code to do this task:
$im=new Imagick('my.png');
$im->setImageFormat('pdf');
$im->writeImage('my.pdf');
Alternatively if you don't have ImageMagick available you could use a commercial API such as Zamzar which supports image to PDF conversion via PHP (more info in the docs).
Code to use this would be:
<?php
// Build request
$endpoint = "https://api.zamzar.com/v1/jobs";
$apiKey = "YOUR_API_KEY";
$sourceFilePath = "my.png";
$targetFormat = "pdf";
$sourceFile = curl_file_create($sourceFilePath);
$postData = array(
"source_file" => $sourceFile,
"target_format" => $targetFormat
);
// Send request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, $apiKey . ":");
$body = curl_exec($ch);
curl_close($ch);
// Process response (with link to converted files)
$response = json_decode($body, true);
print_r($response);
?>
Wrap your image inside HTML and use some HTML to PDF converter like fpdf or mpdf
You can use convertapi service, easy to install:
composer require convertapi/convertapi-php
require_once('vendor/autoload.php');
use \ConvertApi\ConvertApi;
//get api key: https://www.convertapi.com/a/si
ConvertApi::setApiSecret('xxx');
$result = ConvertApi::convert('pdf', ['File' => '/dir/test.png']);
# save to file
$result->getFile()->save('/dir/file.pdf');
to convert multiple files and other options check https://github.com/ConvertAPI/convertapi-php
Here, Php 7.4, Laravel 7+, ImageMagick-7.1.0-Q16, and Ghostscript gs10.00.0 is used.
If any files are contained in the folder JpgToPdf then delete them. And so on.
/**
* jpg To pdf WEB
*
* #method convertJpgToPdf
*/
public function convertJpgToPdf(Request $request)
{
try {
//get list of files
$files = Storage::files('JpgToPdf');
/*get count of files and ,
* check if any files contain
* if any files contains
* then
* get the files name
* delete one by one
*/
if(count($files) >1 )
{
foreach($files as $key => $value)
{
//get the file name
$file_name = basename($value);
//delete file from the folder
File::delete(storage_path('app/JpgToPdf/'. $file_name));
}
}
if ($request->has('jpeg_file'))
{
$getPdfFile = $request->file('jpeg_file');
$originalname = $getPdfFile->getClientOriginalName();
$path = $getPdfFile->storeAs('JpgToPdf', $originalname);
}
// file name without extension
$filename_without_ext = pathinfo($originalname, PATHINFO_FILENAME);
//get the upload file
$storagePath = storage_path('app/JpgToPdf/' . $originalname);
$imagick = new Imagick();
$imagick->setResolution(300, 300);
$imagick->readImage($storagePath);
$imagick->setImageCompressionQuality( 100 );
$imagick->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$imagick->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
$imagick->writeImage( storage_path('app/JpgToPdf/') . $filename_without_ext .'.pdf' );
return response()->download(storage_path('app/JpgToPdf/') . $filename_without_ext .'.pdf' );
} catch (CustomModelNotFoundException $exception) {
// Throws error exception
return $exception->render();
}
}
For just a few images, do it manually and easily with the Chrome web browser. You wont need an internet connection.
Save the following with .html extension in the same folder of your image:
<html>
<body>
<img src="image.jpg" width="100%">
</body>
</html>
Open the html file with Google Chrome,
Crtl + P, to open the print dialog
Choose Save as PDF, to save it locally
Alternatively, you could send a copy to your smatphone via Google Cloud Print

Categories