Laravel 5.1 Snappy pdf image not rendering in pdf file
Asked Answered
P

2

6

I am using barryvdh/laravel-snappy to generate pdf file. I have two image files 1. yourlogohere.png is in public/image/ folder and 2. logo2.png is in folder other than public i.e. storage/app/logo and to get this file I defined a route (www.example.org/logo/logo.png) and use following code to access it.

public function logo($filename)
{
    $file = Storage::disk('local_logo')->get($filename);
    $mime = 'image/png';
    return (new Response($file, 200))->header('Content-Type', $mime);
}

Problem:

When I use following code to generate pdf from the html containing the first file, pdf contains the yourlogohere.png image

$snappy = App::make('snappy.pdf');
$html='<img src="http://www.example.org/images/yourlogohere.png" class="img-responsive" alt="Your Logo Here">';
$snappy->generateFromHtml($html, $path,[],$overwrite = true);

your logo here image appeared in pdf

But when I do exact same thing for the second file, pdf does not render the image.(When I open the link http://www.example.org/logo/logo2.png in browser I get the image). What am I missing?

$snappy = App::make('snappy.pdf');
$html='<img src="http://www.example.org/logo/logo2.png" class="img-responsive" alt="Your Logo Here">';
$snappy->generateFromHtml($html, $path,[],$overwrite = true);

image is not rendered only a rectangle appeared

Thanks,

K

Poser answered 23/10, 2015 at 20:4 Comment(0)
P
5

I think I got the what the problem is, the route to access the image is via auth, even when user is logged in while accessing the snappy, the wkhtmltopdf exe runs in a shell that is totally different session. Now the right fix would be to be embed the image in the html that is sent to snappy instead of the link, Which I am not sure how I will do? Any suggestions welcome there.

Update: I as able to convert the image to data:image/png;base64, and embed it in html.

$html = view('mytemplate.default', compact('variable1', 'variable2'))->render();

/*Convert logo image to base64 before pdf conversion*/

//search for <img src="http://example.org/mytemplate/logo/logo1.png">" and replace the src with data:image/png;base64,
$search = '/(<img\s+src=["\'])([^"\']+)(\/mytemplate\/logo\/)(.*)(\.)(.*?)(["\']\s+[^>]+>)/'; 

$html = preg_replace_callback($search, function ($matches) use ($invoicedetail) {

    $filename = $matches[4] . $matches[5] . $matches[6];
    $file = Storage::disk('local_logo')->get('yourlogohere.png');
    $mime = "image/png";
    $mytemplate = MyTemplate::where('logo_filename', '=', $filename)->first();
    if (!empty($mytemplate)) {
        $file = Storage::disk('local_logo')->get($mytemplate->logo_filename);
        $mime = $mytemplate->logo_mime;
    }
    $base64 = 'data:' . $mime . ';base64,' . base64_encode($file);
    return $matches[1] . $base64 . $matches[7];
}, $html);

$pdf_filename = 'template' . $mytemlpate->id . '.pdf';
$path = storage_path('app' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $filename);
$snappy = App::make('snappy.pdf');
Poser answered 25/10, 2015 at 6:59 Comment(5)
I am facing the same problem now. And thats a Great solution, but what about images greater than 2 MB, php can run into memory problems. I have used that approach before and got many memory problems.Directed
Yes, It will be a problem with larger images, may be you need to optimize the image before Base64 into this.Poser
So what approach would you use to optimize an image before ecoding in b64?Directed
If your images are accessible publicly, you may use them with img tag without converting to base64. the above solution is when image is not accessible to wkhtmltopdf via web.Poser
I have not run any optimizations on image, as in may case all were relatively very small images. you may have a look at image.intervention.io php image manipulation library that can be run to resize image to predetermined size, before converting to base 64Poser
O
13

You can also do:

<img src="data:image/jpeg;base64,
{{ base64_encode(@file_get_contents(url('your.image.url'))) }}">
Octane answered 3/10, 2017 at 14:52 Comment(3)
When the url is controller call to access to image, (image is rendered by controller get method), your solution does not work. We need to access to image itself on server.Hazlett
@Marius you are geniusHomeomorphism
This is exactly what I am doing in my code, but my code is also doing it for all img tags in html code, also figuring the right mime.Poser
P
5

I think I got the what the problem is, the route to access the image is via auth, even when user is logged in while accessing the snappy, the wkhtmltopdf exe runs in a shell that is totally different session. Now the right fix would be to be embed the image in the html that is sent to snappy instead of the link, Which I am not sure how I will do? Any suggestions welcome there.

Update: I as able to convert the image to data:image/png;base64, and embed it in html.

$html = view('mytemplate.default', compact('variable1', 'variable2'))->render();

/*Convert logo image to base64 before pdf conversion*/

//search for <img src="http://example.org/mytemplate/logo/logo1.png">" and replace the src with data:image/png;base64,
$search = '/(<img\s+src=["\'])([^"\']+)(\/mytemplate\/logo\/)(.*)(\.)(.*?)(["\']\s+[^>]+>)/'; 

$html = preg_replace_callback($search, function ($matches) use ($invoicedetail) {

    $filename = $matches[4] . $matches[5] . $matches[6];
    $file = Storage::disk('local_logo')->get('yourlogohere.png');
    $mime = "image/png";
    $mytemplate = MyTemplate::where('logo_filename', '=', $filename)->first();
    if (!empty($mytemplate)) {
        $file = Storage::disk('local_logo')->get($mytemplate->logo_filename);
        $mime = $mytemplate->logo_mime;
    }
    $base64 = 'data:' . $mime . ';base64,' . base64_encode($file);
    return $matches[1] . $base64 . $matches[7];
}, $html);

$pdf_filename = 'template' . $mytemlpate->id . '.pdf';
$path = storage_path('app' . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $filename);
$snappy = App::make('snappy.pdf');
Poser answered 25/10, 2015 at 6:59 Comment(5)
I am facing the same problem now. And thats a Great solution, but what about images greater than 2 MB, php can run into memory problems. I have used that approach before and got many memory problems.Directed
Yes, It will be a problem with larger images, may be you need to optimize the image before Base64 into this.Poser
So what approach would you use to optimize an image before ecoding in b64?Directed
If your images are accessible publicly, you may use them with img tag without converting to base64. the above solution is when image is not accessible to wkhtmltopdf via web.Poser
I have not run any optimizations on image, as in may case all were relatively very small images. you may have a look at image.intervention.io php image manipulation library that can be run to resize image to predetermined size, before converting to base 64Poser

© 2022 - 2024 — McMap. All rights reserved.