Symfony 406 (Not Acceptable) - image

I am trying to set image path with controller, because i choose to add my image uploaded out of web/ directory.
I create an ServeController :
public function urlAction($filename)
{
$path = "../data/uploads/admin/";
$response = new BinaryFileResponse($path.$filename);
$response->headers->set('Content-Type', 'image/jpeg');
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE);
return $response;
}
This work from my frontend reactJs, but with i am trying to display the image on my symfony backoffice i have got error 406 Not Acceptable
In my twig template i am using {{url('url_image', {'filename' : data.filename }) }}
Any ideas ?

Can you try this:
public function urlAction($filename)
{
$path = "../data/uploads/admin/";
$response = new Response();
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_INLINE, $filename);
$response->headers->set('Content-Disposition', $disposition);
$response->headers->set('Content-Type', 'image/jpeg');
$response->setContent(file_get_contents($path));
return $response;
}
Not sure if that will fix it though. Please try it.

Related

Laravel unlink method

can someone tell me how to unlink image from public path when product is deleted.
My current code which does not work:
public function destroy($id)
{
$product = Product::findOrFail($id);
$image_path = '/uploads/products/' . $product->image;
if(file_exists($image_path)){
unlink($image_path);
}
$product->delete();
}
Also tried:
$product = Product::findOrFail($id);
if(file_exists($product->image)){
unlink($product->image);
}
$product->delete();
Also I am using accessor so my $product->image is returning:
"http://myeshop.local/uploads/products/1593902362bluesocksupd.jpg"
Here is accessor code:
public function getImageAttribute($image){
return asset($image);
}
use model deleted event
//Product Model
protected static function boot()
{
parent::boot();
static::deleted(function($product){
// getOriginal skip accessor
$image = public_path('uploads/products/' . $product->getOriginal('image'));
if(file_exists($image)) {
unlink($image);
}
});
}
unlink($path) is a PHP function. It will delete a file located at a local path. According to your question the value of $product->image is the complete URL to the image. If it is then the following is true:
$product = Product::findOrFail($id);
$image_path = '/uploads/products/' . $product->image;
// $image_path = '/uploads/products/http://myeshop.local/uploads/products/1593902362bluesocksupd.jpg'
// and it needs to point to '/PATH/TO/LARAVEL/uploads/products/1593902362bluesocksupd.jpg'
// the following file_exists() will return false
if(file_exists($image_path)){
unlink($image_path); // so you never get here
}
There are some quick and dirty ways to fix this, but the best thing to do is to have the $product->image property point to just the name of the file. Then in your view apply the file name to the /uploads/products/ directory on the web server.
Doing this will allow you to apply the /uploads/products/ local path and have a better time finding the file you want to delete. I'm assuming the uploads directory is in your Laravel public directory so you'd want to do something like this:
// $product->image must point to the filename only: 1593902362bluesocksupd.jpg
// The file_exists should evaluate to true and unlink() will work.
$image_path = public_path('uploads/products/' . $product->image);
if(file_exists($image_path)){
unlink($image_path);
}
In your Blade template view you'd need to show the product image using something like this:
<img src="{{ url('/uploads/products/' . $product->image) }}" />
Storing a complete URL in your database doesn't scale well if you wanted to develop another website or reuse this code on another project. This way you can let Laravel manage where the URL or local file system is.
You could use PHP's unlink() method.
But if you want to do it the Laravel way, use the Storage::delete method instead :
use Illuminate\Support\Facades\Storage;
public function destroy($id)
{
$product = Product::findOrFail($id);
$image_path = public_path('uploads/products/' . $product->image);
if(file_exists($image_path)){
Storage::delete($image_path);
}
$product->delete();
}

The image cannot be displayed because it contains errors laravel

I am working on a laravel project in which I am trying to show image using url but getting error. I have tried a lot and search everything but I don't understand why I am getting this error. I am using the below function
public function displayImage($filename){
$path = storage_path("app/taskImage/".$filename);
if (!File::exists($path)) {
abort(404);
}
$file = File::get($path);
$type = File::mimeType($path);
$response = \Response::make($file, 200);
$response->header("Content-Type", $type);
return $response;
}
And the route is
Route::get('taskImg/{filename?}', [
'uses' => 'FormController#displayImage',
]);
And the URL which I am tring is like
http://localhost/project_name/public/taskImg/test.jpg
when I have print something I am getting the that but Not getting the Image. It is showing a blank screen with error message The image cannot be displayed because it contains errors
you can do it like this way
$storagePath = storage_path("app/taskImage/".$filename);
return Image::make($storagePath)->response();
I've spent a LOT of hours searching for a solution for this, I found it at last! just add ob_end_clean before returning the response, like the following:
ob_end_clean();
return response()->file($path,['Content-type' => 'image/jpeg']);
I can't explain because I don't know what was going on, any one could explain this?

How to pass whole url as params?

I want allow user to scan QR code and go to website. This is search results with params in url address like
http://example.com/qr-code/http://example.org/search/user_id=12&model_id=4&role_id=8
My route is set as
Route::get('qr-code/{data?}/{size?}', 'QrController#qrCode')->name('qr-code');
so i hope my $data will get url:
http://example.org/search/user_id=12&model_id=4&role_id=8
My Controller has
public function qrCode(Request $request, $data = null, $size = 60) {
dd(88);
$data = (empty($data)) ? env('APP_URL') : $data;
return view('qr.code')->with('qr', QrCode::size($size)->generate($data));
}
But i can't even see dd(88) route redirect to main page.
How can i fix that ?
The thing is that Laravel doesn't know that you will provide an entire URL as a parameter. He could interpret everything like that:
http://example.com/qr-code/http:/ /search/user_id=12&model_id=4&role_id=8 . Try encoding the URL diffrently. Your $data will be "http:/" and your size will be 60.
Ok i took i added to helper
function base64url_encode($s) {
return str_replace(array('+', '/'), array('-', '_'), base64_encode($s));
}
function base64url_decode($s) {
return base64_decode(str_replace(array('-', '_'), array('+', '/'), $s));
}
And then i am getting URI from request on view like
Click me
From JS i send params to QrController
public function qrCode(Request $request, $data = null, $type = null, $size = 200) {
$data = (empty($data)) ? env('APP_URL') : $data;
if ($type == 'url') $data = env('APP_URL') . base64url_decode($data);
return view('qr.code')->with('qr', QrCode::size($size)->generate($data));
}
And works fine. Base64 has + or / sometimes so thats why need to replace both - and _ and second is i add base url from env to make whole address.
Thx

Write function in controller below controller class?

Is that a good practice to wrap some code from controller class method because it's too long and put that code in another custom function below controller class.
Here is controller method:
public function store(UploadRequest $request)
{
//Provjera duljine imena slike (max 20 znakova)
if(!is_valid_name($request->file('file'))) {
return redirect()->back()->withErrors(['File name can\'t be longer than 20 characters.']);
}
$user = Auth::user();
$time = time();
$image = $request->file('file');
//Dodaj trenutno vrijeme prije imena slike kako bi se slika mogla identificirati
$image_name = $time . $image->getClientOriginalName();
//Ako je slika png spremi ju bez konverzije
if($image->getClientOriginalExtension() == "png")
{
Storage::put('public/images/'.$user->id.'/png/'.$image_name, file_get_contents($image));
save_image_to_database($image, $user, $time);
}
Save_image_to_database() is my custom function that is written below controller class:
function save_image_to_database($image, $user, $time){
$db_image = new Image();
if($image->extension() == 'png')
{
$db_image->path = $time . $image->getClientOriginalName();
$db_image->png_size = $image->getClientOriginalSize();
}
else
{
$path = $time . pathinfo($image->getClientOriginalName(), PATHINFO_FILENAME).'.png';
$png_size = Storage::size('/public/images/'.$user->id.'/png/'.$path);
$db_image->path = $path;
$db_image->png_size = $png_size;
}
$db_image->user_id = $user->id;
$db_image->extension = $image->extension();
$db_image->size = $image->getClientSize();
$db_image->save();
return redirect('/images');
}
Problem is that redirect() method in custom function is not working, it redirects to blank window but the path in browser "localhost:8000/images" is correct.When I manually refresh the site then it works and the view is returned. If I move that redirect() method from custom function to controller store() then it works well.
Your function returns Response object but controller doesn't use it
The most simple solution for you will be to return the response of helper function like
return save_image_to_database($image, $user, $time);
However I would at least wrap it in try-catch to handle inability to save file like
try {
save_image_to_database($image, $user, $time);
} catch (\Exception $e) {
// return error response
}
// if we got here image was successfully saved
return redirect('/images');
Now back to your question about if its a good experience to handle image as another controller method.. I'd say no, you want to keep your controllers very skinny and have only methods that are used by Router
I'd either move it into a Trait (Traits in PHP) and use that trait in the controller or make an Image Service and use it via dependency injection.

Render part of a view in middleware?

I'm trying to have some after middleware so that if the request was ajax, only render part of the view. I'm having issues though.
My method in my controller:
$data = $this->repository->getUser($id);
$view = View::make('site.user')->withData($data);
return $view;
My middleware:
$response = $next($request);
if(Request::ajax()){
$response->renderSections()['content'];
}
return $response;
I get the error:
Call to undefined method Illuminate\Http\Response::renderSections()
To get the response you need to use a after Middleware which is you are doing now so, you have response as given below:
$response = $next($request);
Now you may try this:
$content = $response->getOriginalContent()->renderSections()['content']

Resources