How to cache images from url in Laravel - php

I have a Laravel 4 application that displays images from another PHP application that is located on a remote server.
I would like to know what is the best solution to cache the images from the remote server on my local Laravel App.
Please note that it's almost impossible to copy/past the entire images directory from the remote server, since there are more than 150k images that are regurlary updated (every minutes) and there is a database correlation too (filename with column value in database).
I was about to use Rsync to sync the two directories (distant with local), but I also need to resize images before displaying them and organize the images subdirectories in a different way than it is on the remote server.
First I have installed the Intervention Image Class package on Laravel and I have created a Route:
Route::get('photos/item/{size}/{reference}/{photo}', 'ImgController#showImg');
And in the ImgController:
public function showImg( $size, $reference, $photo )
{
switch ( $size ) {
case '300x225':
$jpg = Image::make( 'http://myremoteapp.com/uploads/' . $reference . '/' . $photo )->resize( 300, 225 )->response( 'jpg' );
break;
}
return $jpg;
}
This works but it doesn't keep the images in the browser's cache and it also creates a performance issue, since the images have to be downloaded and resized every time the page is opened.
I have heard about the Intervention Image Cache but I am not sure if it works with images taken from URLs.
Any advice and suggestions on how to resolve this in a proper way would be greatly appreciated.

You can use cache route as:
Route::filter('cache', function($route, $request, $response = null) {
$key = 'route-' . safe_title(URL::full());
if( is_null($response) && Cache::has($key) ) {
return Cache::get($key);
} elseif( !is_null($response) && !Cache::has($key) ) {
// Code this here
Cache::put($key, $response->getContent(), 30);
}
});
Route::group(array( 'before' => 'cache', 'after' => 'cache' ), function() {
Route::get('photos/item/{size}/{reference}/{photo}', 'ImgController#showImg');
});
attention :
Route::filter() was wiped away from Laravel since > 5.0

Related

Laravel Azure Blob Storage Cache Images

this is my scenario:
I have a Laravel 6.x application and I'm using the FlySystemAzureBlobStorage package to store images on Azure Blob Storage.
Then I want to use the InterventionImageCache package to get and cache the images for faster client's downloads in different sizes.
I've already done it in this way:
public static function getImageResponseForApi($storageDiskName, $imagePath, $width = null, $height = null)
{
//check if the image exists on disk
$exists = empty($storageDiskName) ?
Storage::exists($imagePath) :
Storage::disk($storageDiskName)->exists($imagePath);
if ($exists) {
$image = empty($storageDiskName) ?
Storage::get($imagePath) :
Storage::disk($storageDiskName)->get($imagePath);
if (!empty($width) || !empty($height)) {
//use the image cache function to get the cached image if exists
$image = \Image::cache(function ($ima) use ($image, $width, $height) {
//check if height and with are higher than original or not
$ima->make($image)->resize($width, $height, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
});
}
$sizes = getimagesizefromstring($image);
$headers = [
'Content-Length' => strlen($image),
'Content-Type' => $sizes["mime"]
];
return \Response::make($image, 200, $headers);
} else {
return null;
}
}
There is a problem working in this way: I must download the image from azure blob storage before the system can check if a resized cached version of it exists.
The Azure package i'm using doesn't provide the possibility to get the image paths, so I can't find another solution to my problem.
So, is there a way to achieve the image caching without I have to download the file every time?
I use a separate route for showing/caching the image in my blade.
I store the image as BLOB in MYSQL PRODUCT table identified by product_id
BLADE:
<img src="/dbimage/{{$product->id}}.png" >
ROUTE:
Route::get('/dbimage/{id}',[ProductImageController::class, 'getImage']);
CONTROLLER:
class ProductImageController extends Controller
{
public function getImage($prodcutImageID){
$productID=explode(".",$prodcutImageID);
$rendered_buffer= Product::all()->find($productID[0])->image;
$response = Response::make($rendered_buffer);
$response->header('Content-Type', 'image/png');
$response->header('Cache-Control','max-age=2592000');
return $response;
}
}
This makes the browsers cache the images

intervention image for thumbnails Laravel 5

Hi I'm trying to get thumbnails with the same TimThumbs, I'm using Intervention Image and Intervention Cache.
My thumbnails now have the url structure:
thumbs/122x88?src=upload/news/news_40942c468090384b8135a6bbb79f631d.png
How do I get an address like:
/thumbs/upload/news/122x88-news_40942c468090384b8135a6bbb79f631d.png
I would like to remove this "?src="?
My route code is as follows:
Route::get('thumbs/{imgw}x{imgh}/', function ($imgw,$imgh)
{
$src = \Input::get('src', 1);
$width = $imgw;
$height = $imgh;
$cacheimage = \Image::cache(function($image) use ($src,$width,$height) {
return $image->make($src)->resize($width,$height);
}, 1, false);
return Response::make($cacheimage, 200, array('Content-Type' => 'image/jpeg'));
});
I tried to remove "\Input::get", but It's not working.
Check it out how I get the pictures on my website:
https://www.verhuisdieren.nl/
So on imagecache.php ( config file ), i just setup the route for all the images ( lets say 'route' => 'images' ), and when I upload images, I upload them on the storage folder and rename them before I save them. From Laravel 5.3 you can save it with the FileUploader class like this:
$request->get('image')->save('new-name');
and this then loads it without any prefix.
So recap: don't make a route for it, you already have that on your imagecache.php file. You can then get the route something like this:
url(config('imagecache.route'), ['YOUR-SIZE', 'FILENAME']);
EDITED:
config file example ( the config file imagecache.php ):
https://pastebin.com/sf5CusYJ

Zend Framework 3: create download link for generated file

I'm writing an app that lets the user upload an Excel file. It checks the file for errors, then, if no errors are found, it uploads the contents to a database. If it does find errors, the cells containing errors are colored red, then the file is saved. I then want to create a download link to this file so the user can check where they made mistakes.
The problem is that I am not sure how to create this link and where to store the file. I modify the file like this:
foreach ($badCells as $bcell) {
$sheet->getStyle($bcell)->applyFromArray(array(
'fill' => array(
'type' => \PHPExcel_Style_Fill::FILL_SOLID,
'color' => array('rgb' => 'FF4444')
)
));
}
And then save it with
$objWriter->save($dldir . $formData['upload']['name']);
$dldir is created with
$dldir = "/download/";
if (file_exists($dldir)) {
if (!is_dir($dldir)) {
unlink($dldir);
mkdir($dldir);
}
} else {
if(!is_dir($dldir)) {
mkdir($dldir);
}
}
Is this even the right way to do this? Can I store the files in any old folder or do they have go somewhere specific? How do I create the link to the specific file in the view for the user and make it accessible so they can download it?
I may be wrong .
For file upload i use this library Gargron/fileupload
The function bellow help to upload file to a specific folder and return full link of the file. You can save the link in DB
function uploadFile ($file){
$validator = new \FileUpload\Validator\Simple('5M');
$pathresolver = new \FileUpload\PathResolver\Simple($_SERVER['DOCUMENT_ROOT'].'/upload_folder');
$filesystem = new \FileUpload\FileSystem\Simple();
$fileupload = new \FileUpload\FileUpload(file, $_SERVER);
$fileupload->setPathResolver($pathresolver);
$fileupload->setFileSystem($filesystem);
$fileupload->addValidator($validator);
$md5Generator = new \FileUpload\FileNameGenerator\MD5 (true);
$fileupload->setFileNameGenerator($md5Generator);
list($files) = $fileupload->processAll();
foreach($files as $file){
if ($file->completed) {
return $_SERVER['DOCUMENT_ROOT'].'/upload_folder/'.$file->getFileName()) ;
}
}
}
Thanks for the help, I managed to figure it out over the weekend. Here's how I did
it:
$filename = join(DIRECTORY_SEPARATOR, array($dldir, $formData['upload']['name']));
$objWriter->save(str_replace(__FILE__,$filename,__FILE__));
This is how I save the file, using DIRECTORY_SEPARATOR so it will work correctly on both Windows and Linux.
return $this->redirect()->toRoute('import', ['action' => 'reject'],['query' => ['q' => 'file', 'name' => $filename]]);
In the controller, I redirect the route to the correct action and pass the file name on to it via a query URL.
public function rejectAction()
{
$filename = $this->getRequest()->getQuery('name', null);
return new ViewModel(array('filename' => $filename));
}
There, I obtain said file name through getRequest()->getQuery() and pass it on to the viewmodel.
Right-click here and choose 'Save As' to download your file.
And finally, this is how it shows the link in reject.phtml.
Downloading only works with right click and save as, I suspect I will have to write some sort of file handler to make ZF produce the correct headers for a normal left click download.

Display the image files from the storage

I'm on Laravel 5.3 and I'm having trouble rendering the file images from Laravel Storage to my html/blade.
My filesystems.php default driver
'default' => 'public'
How to render the file images from the 'Storage' to view/html/blade
I tried this,
//path for image from the storage
Route::get('/app/system/sale-items/item/{username}/{item_id}/{image}', function($image,$item_id,$username)
{
$path = storage_path().'/app/public/'.$username.'/'.$item_id.'/'. $image;
if (file_exists($path)) {
return Response::download($path);
}
});
but seem's not working like the image is not showing, it fails to retrieved the image from the 'Storage'. Any help, ideas please?
I figured it out already, I just use
//path for image from the storage
Route::get('/app/system/sale-items/item/{username}/{item_id}/{image}', function($username,$item_id,$image)
{
$path = storage_path().'/app/public/'.$username.'/'.$item_id.'/'. $image;
if (file_exists($path)) {
return Response::download($path);
}
});

php, data not updating after form post in zend?

this might be a bit of a novice question and here is my situation:
i have a upload form for uploading images. and in my editAction i do:
if ($request->isPost()) {
if (isset($_POST['upload_picture']) && $formImageUpload->isValid($_POST)) {
//here i will add the picture name to my database and save the file to the disk.
}
}
$picVal = $this->getmainPic(); // here i do a simple fetch all and get the picture that was just uploaded
$this->view->imagepath = $picVal;
what happens is that the newly uploaded picture doesn't show. I checked the database and the dick and the file is there.
im thinking the problem might be the order of the requests or something similar.
any ideas?
edit: another thing is that in order to make the new image come up i have to do a SHIFT+F5 and not only press the browser refresh button
edit2: more code
i first call the upload to disk function then if that returns success addthe file to the database
$x = $this->uploadToDiskMulty($talentFolderPath, $filename)
if($x == 'success'){
$model->create($data);
}
the upload function
public function uploadToDiskMulty($talentFolderPath, $filename)
{
// create the transfer adapter
// note that setDestiation is deprecated, instead use the Rename filter
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addFilter('Rename', array(
'target' => $filename,
'overwrite' => true
));
// try to receive one file
if ($adapter->receive($talentFolderPath)) {
$message = "success";
} else {
$message = "fail";
}
return $message;
}
If the picture only appears when you do SHIFT+F5 that means it's a caching problem. Your browser doesn't fetch the image when you upload it. Do you use the same file name?

Categories