I want to download a remotely hosted image using codeiogniter . and a validation feature also has to be added so that only images are downloaded..
is it possible to use the built in functions offered by CI ??
thanks .
To get a remote image, you can just use file_get_contents, assuming allow_url_fopen is set to on in php.ini.
$image=file_get_contents('http://othersite.com/image.jpg');
Once you have that, you can validate the file extension, or try and resize the image to check that it really is an image.
This solution is not from CI but PHP, think it can be usefull anyway.
May be checking the image size is enough to be sure it's an image, like
$imagedata = getimagesize('http://othersite.com/image.jpg');
or use exif_imagetype
if ( ! function_exists( 'exif_imagetype' ) ) {
function exif_imagetype ( $filename ) {
if ( ( list($width, $height, $type, $attr) = getimagesize( $filename ) ) !== false ) {
return $type;
}
return false;
}
}
if( exif_imagetype('http://othersite.com/image.jpg') )
{
//is an image
}
Related
I am migrating my existing PHP program to Laravel. I know the upload should be $request->files->store('images'); but this doesn't compress the images beforehand.
I have found Intervention Image plugin for Laravel but I don't want to use it because I want it to be pure PHP only.
My working code from pure PHP was:
$info = getimagesize($tmpFilename);
if ($info['mime'] == 'image/jpeg') {
$image = imagecreatefromjpeg($tmpFilename);
} else if ($info['mime'] == 'image/gif') {
$image = imagecreatefromgif($tmpFilename);
} else if ($info['mime'] == 'image/png') {
$image = imagecreatefrompng($tmpFilename);
}
imagejpeg($image, $path, 60);
I know the images get saved at /storage/app/public/ so I used that path for imagejpeg as well. This is my laravel code:
$tmp_file = $inner->getPathName();
imagejpeg($tmp_file, '/storage/app/public/images/hehe.jpg', 60);
But it doesn't work. It only says
imagejpeg(/storage/app/public/images/hehe.jpg): failed to open stream: No such file or directory
Any help would be appreciated
I am performing SSH in Laravel whereby I connect to another server and download a file. I am using Laravel Collective https://laravelcollective.com/docs/5.4/ssh
So, the suggested way to do this is something like this
$result = \SSH::into('scripts')->get('/srv/somelocation/'.$fileName, $path);
if($result) {
return $path;
} else {
return 401;
}
Now that successfully downloads the file and moves it to my local server. However, I am always returned 401 because $result seems to be Null.
I cant find much or getting the result back from the SSH. I have also tried
$result = \SSH::into('scripts')->get('/srv/somelocation/'.$fileName, $path, function($line){
dd( $line.PHP_EOL);
});
But that never gets into the inner function.
Is there any way I can get the result back from the SSH? I just want to handle it properly if there is an error.
Thanks
Rather than rely on $result to give you true / false / error, you can check if the file was downloaded successfully in another way:
// download the file
$result = \SSH::into('scripts')->get('/srv/somelocation/'.$fileName, $path);
// see if downloaded file exists
if ( file_exists($path) ) {
return $path;
} else {
return 401;
}
u need to pass file name also like this in get and put method:
$fileName = "example.txt";
$get = \SSH::into('scripts')->get('/remote/somelocation/'.$fileName, base_path($fileName));
in set method
$set = \SSH::into('scripts')->set(base_path($fileName),'/remote/location/'.$fileName);
in list
$command = SSH::into('scripts')->run(['ls -lsa'],function($output) {
dd($output);
});
I'm using Laravel 4 with dompdf package: https://github.com/barryvdh/laravel-dompdf
When I generate a report and it converts it to PDF on my local, everything is fine and displays well, but when I do the same exact thing on my production server, it displays random letters where there is either dynamic or static content.
Screenshot of local vs production:
http://s28.postimg.org/u5zk3pc19/report_diff.png
Here is the code that creates the PDF:
/**
* Create PDF
*
*/
public function createPdf( $reportData )
{
if( $this->validate() )
{
// Get Final Data Information
$btu_hp = static::getBtuHp( $reportData['booth_cfm'], $reportData['cure_temp_hp'], $reportData['outside_temp'] );
$btu_current = static::getBtuCurrent( $reportData['booth_cfm'], $reportData['bake_temp_current'], $reportData['outside_temp'] );
$reportData['energy_percentage_per_unit'] = static::getEnergyPercentagePerUnit( $btu_hp, $btu_current );
$reportData['energy_dollar_per_unit'] = static::getEnergyDollarPerUnit( $reportData['cost_per_therm'], $reportData['bake_time_current'], $reportData['cure_time_hp'], $btu_current, $btu_hp );
$reportData['time_savings_per_unit'] = static::getTimeSavingsPerUnit( $reportData['bake_time_current'], $reportData['cure_time_hp'] );
$reportData['time_savings_per_year'] = static::getTimeSavingsPerYear( $reportData['time_savings_per_unit'][0], $reportData['units_per_day'], $reportData['production_days'] );
$reportData['labor_dollar_per_year'] = static::getLaborDollarPerYear( $reportData['labor_rate'], $reportData['time_savings_per_year'][0] );
$reportData['energy_dollar_per_year'] = static::getEnergyDollarPerYear( $reportData['energy_dollar_per_unit'][0], $reportData['units_per_day'], $reportData['production_days'] );
$view = View::make('pages.report.hp-report.print', array('report' => $reportData));
if( ! $this->saveAsPdf($view, $this->generateFileName()) )
{
return false;
}
return true;
}
return false;
}
/**
* Save report as PDF
* #param html HTML of PDF
* #param fileName Name of File
*
*/
public function saveAsPdf( $html, $fileName = null )
{
if(is_null($fileName))
$fileName = $this->generateFileName();
$htmlPath = $this->reportDirectory.'/'.$fileName.'.html';
$pdfPath = $this->reportDirectory.'/'.$fileName.'.pdf';
file_put_contents( $htmlPath, $html );
// set recent PDF to name of PDF
$this->recentReportFile = $fileName . '.pdf';
return PDF::loadFile($htmlPath)->save($pdfPath);
}
/**
* Get most recent uploaded PDF
*
*/
public function getRecentPdf()
{
return $this->recentReportFile;
}
/**
* Generate file name for PDF
*
*/
public function generateFileName()
{
return Auth::user()->id . '_hp_' . str_random(10) . '_' . time();
}
Everything writes fine and it uses the right template and has the styling... Only the static content and dynamic content (values written out with PHP variables) display badly, although you can see some of the static content like Energy Savings and such prints fine.
Is there a reason this could be all jumbled up on the live server, but not local?
Here is the HTML for the view that is being grabbed (the HTML the php variables are injected into): http://pastebin.com/5bMR6G2s
And here is my config file for dompdf:
http://pastebin.com/Ld6MQckG
There are two possible causes for this:
Missing font(s) on the production server. Make sure you have the correct fonts installed on the production site.
Character encoding issues. I'm not sure which site (dev/live) the issue is on, but it may be that one is outputting UTF-8 and the other is not. You could try to sort this out by detecting the encoding on the input file on both dev and live by using mb_detect_encoding and see if they're different. If they are, then use mb_convert_encoding before converting to PDF.
Image Move to folder using the tool move ()...
But when I want to display it in html showing me the full path...
for example on inspect elements show this: /opt/lampp/htdocs/app/uploads/
develop my app on localhost
$destinationPath = 'uploads/';
$filename = Input::file('file')->getClientOriginalName();
Input::file('file')->move($destinationPath, $filename);
Keep in mind only the "public" directory is actually web accessible, so if you are moving something to anything not in "public", then it won't be web accessible. You can get around this by either a) moving it to somewhere in your 'public' directory, and then building a url to that (I suggest URL::to('/path/to/your/file')), or you can build a controller function which simply spits out your file.
I have done something similar in my app, with a controller that grants access (to authorized users only) to view uploaded content in a folder under app/userdocs:
// Read file then spit it out
$filepath = $doc->file;
$imagecontents = File::get(app_path().'/userdocs/' . $filepath);
if ($ext == "jpg" || $ext == "jpeg" || $ext == "png" || $ext == "gif")
{
$contentType = "image/$ext";
}
else
{
$contentType = "application/octet-stream";
}
return Response::make($imagecontents, 200, array('Content-Type' => $contentType));
EDIT
I tried debugging this with xdebug and netbeans. It's weird that the exports will work during the debug session if I put in some breakpoints. However, with no break points, a more realistic environment, the exports don't work.
I've tried adding sleeps into some parts of the code.
I think that maybe PHP is ending before the Redis commit is completed. Maybe the Redis connections are being done asynchronously, but I checked PRedis and the default is a synchronous connection.
I am working on a reporting tool.
Here is the basic issue.
We store a report into the session object but on later requests when we try to get to the report in the session object it's gone.
Here is a more detailed version.
I store a 'report' object into the session like so
$_SESSION['report_name_unixtimestamp'] = gzcompress( serialize( $reportObject ) );
The user sees the report in some table form and then if they want they can export it. The report could change so the idea behind storing it in the session like this is that when the user exports it to PDF, Excel, etc, they'll be getting a report identical to the one they are viewing.
The user clicks on an export button and on the PHP side it will go into the session, fetch the report via the key provided as a get parameter (uncompresses and unserializes it), create the export and send it to the user for download.
This has worked well up until the point that we tried to introduce the Redis caching server as a tool for better session management.
What happens now is the following:
The first time we run the report it will get stored into the cache and the export will work successfully.
We will run the report again, with the same user account in the same session. This changes the unixtimestamp and so there should be two entries in the $_SESSION. ( $_SESSION['report_name_oldertimetamp'] and $_SESSION['report_name_newertimestamp'] ). When we click on the export button again we get an error saying that the file doesn't exist ( because it hasn't been sent by the server ).
If we check the redis server for the newer version of the report it isn't there, but the old timestamp is still there.
Now, this worked with the file session management but not with Redis. we've tried the redis module for php as well as the pure php client Predis.
Does anyone have any ideas?
Here are a few more details :
Redis has NOT run out of memory. We've checked this many times.
We already know that to unserialize the report object in the session the report class has to be included already. ( remember, the first export works fine but anything after that fails )
If we check the php session object during the request that the report is running on, it WILL contain the newer report but it never makes it to Redis.
Below is the save handler that is being used with Predis.
The redis_session_init is the function I call right before session_start() so that it gets registered. I'm not sure how the redis_session_write function works though so maybe someone can help me with that.
<?php
namespace RedisSession
{
$redisTargetPrefix = "PHPREDIS_SESSION:";
$unpackItems = array( );
$redisServer = "tcp://cache.emcweb.com";
function redis_session_init( $unpack = null, $server = null, $prefix = null )
{
global $unpackItems, $redisServer, $redisTargetPrefix;
if( $unpack !== null )
{
$unpackItems = $unpack;
}
if( $server !== null )
{
$redisServer = $server;
}
if( $prefix !== null )
{
$redisTargetPrefix = $prefix;
}
session_set_save_handler( 'RedisSession\redis_session_open', 'RedisSession\redis_session_close', 'RedisSession\redis_session_read', 'RedisSession\redis_session_write', 'RedisSession\redis_session_destroy', 'RedisSession\redis_session_gc' );
}
function redis_session_read( $id )
{
global $redisServer, $redisTargetPrefix;
$redisConnection = new \Predis\Client( $redisServer );
return base64_decode( $redisConnection->get( $redisTargetPrefix . $id ) );
}
function redis_session_write( $id, $data )
{
global $unpackItems, $redisServer, $redisTargetPrefix;
$redisConnection = new \Predis\Client( $redisServer );
$ttl = ini_get( "session.gc_maxlifetime" );
$redisConnection->pipeline( function ($r) use (&$id, &$data, &$redisTargetPrefix, &$ttl, &$unpackItems)
{
$r->setex( $redisTargetPrefix . $id, $ttl, base64_encode( $data ) );
foreach( $unpackItems as $item )
{
$keyname = $redisTargetPrefix . $id . ":" . $item;
if( isset( $_SESSION[ $item ] ) )
{
$r->setex( $keyname, $ttl, $_SESSION[ $item ] );
}
else
{
$r->del( $keyname );
}
}
} );
}
function redis_session_destroy( $id )
{
global $redisServer, $redisTargetPrefix;
$redisConnection = new \Predis\Client( $redisServer );
$redisConnection->del( $redisTargetPrefix . $id );
$unpacked = $redisConnection->keys( $redisTargetPrefix . $id . ":*" );
foreach( $unpacked as $unp )
{
$redisConnection->del( $unp );
}
}
// These functions are all noops for various reasons... opening has no practical meaning in
// terms of non-shared Redis connections, the same for closing. Garbage collection is handled by
// Redis anyway.
function redis_session_open( $path, $name )
{
}
function redis_session_close()
{
}
function redis_session_gc( $age )
{
}
}
The issue was solved and it was much dumber than I thought.
The save handler doesn't implement locking in any way. On the report pages there are multiple requests being made to the server via ajax and the like. One of the ajax requests starts before the report gets saved to session space. Thus, it reads the session, then writes the session at the end.
Since the reports executes faster every time, the report would get cached to the session in Redis but would then be overwritten by the other script that had an older version of the sessien.
I had help from one of my co-workers. Ugh! This was a headache I'm glad to be over.