I have an automated email in Laravel PHP which informs the user that a particular product has expired.
I would like to include a base64 image which should be embedded within the email itself.
Is it possible to embed base64 images in a markdown email with Laravel?
If so how?
The following is the email markdown blade template:
#component('mail::message')
![Logo][logo]
[logo]: {{asset('frontend/img/core-img/logo-dark.png')}} "Logo"
**Product Expiry**
Dear {{$userName}},
This is to inform you that your product **{{$listingName}}**.
Your item was removed from the Market Place. Should you wish to re-list the item kindly do so from the app.
![alt]{{$listingImage}}
Should you require any information or need professional assistance kindly get in touch:
#component('mail::button', ['url' => ''])
Contact Us
#endcomponent
Thanks,<br>
# **{{ config('app.name') }} Team**
![App Icon|100x100]({{asset('frontend/img/core-img/app-logo.png')}})
#endcomponent
and the is the class for this email template:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ListingExpiryEmail extends Mailable
{
use Queueable, SerializesModels;
protected $user_name;
protected $listing_name;
protected $listing_image;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user_name, $listing_name, $image)
{
$this->user_name = $user_name;
$this->listing_name = $listing_name;
$this->listing_image = $image;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('MyHurryApp Listing Expiry')->markdown('emails.listings.listingexpiryemail', [
'userName' => $this->user_name,
'listingName' => $this->listing_name,
'listingImage' => $this->listing_image
]);
}
}
Thanks
This works for me
<img src="data:image/png;base64,{{base64_encode(file_get_contents(public_path('/image/logo.png')))}}">
After further research I found out that this is not possible.
As per: https://superuser.com/questions/1199393/is-it-possible-to-directly-embed-an-image-into-a-markdown-document
Markdown documents is just a text file and text editors would not know what to do with a binary image within the "text".
Having said that there might be a way around this limitation:
There are methods like MIME and base64 to encode binary data into a text file in a sense, but most text editors and Markdown-renderers wouldn't know what to do with a MIME encoded document that contains a Markdown text part and a base64 encoded image part.
But I am still looking into a possible solution.
If someone can guide me further would be highly appreciated.
Thanks
Related
I have a validator set up to check if the document we upload is an XML file
if ($request->input('action') == 'upload_document') {
$validator = Validator::make($request->all(), [
'file' => 'bail|required|mimes:application/xml,xml|max:10000',
]
);
}
But when I do my upload, this validator triggers me an error "File must e of type application/xml,xml" even when I drop a real XML file with a .xml extension.
I have in my php.ini config extension=php_fileinfo.dll of course
Note that mime type validation instruct Laravel to read the content of the file to determine its type, so changing an image extension from .jpg to .xml will not trick it
From the Docs
mimes:foo,bar,...
The file under validation must have a MIME type corresponding to one of the listed extensions.
Basic Usage Of MIME Rule
'photo' => 'mimes:jpeg,bmp,png'
Even though you only need to specify the extensions, this rule actually validates against the MIME type of the file by reading the file's contents and guessing its MIME type.
A full listing of MIME types and their corresponding extensions may be found at the following location: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
So make sure your file is an actual valid xml file (try this with phpunit.xml) from your Laravel project
Route::post('/', function (Request $request) {
if ($request->input('action') == 'upload_document') {
$validator = Validator::make(
$request->all(),
[
'file' => 'bail|required|mimes:application/xml,xml|max:10000',
]
);
$validator->validate();
dd('the file is valid');
}
});
And a form like this
<form method="post" enctype="multipart/form-data">
#csrf
<input name="action" value="upload_document">
<input type="file" name="file">
<button type="submit">Submit</button>
</form>
#error('file')
{{ $message }}
#enderror
Result:
"the file is valid"
But when testing with image.xml
The file must be a file of type: application/xml, xml.
Alternatively, you can validate by extension
Route::post('/', function (Request $request) {
if ($request->input('action') == 'upload_document') {
$request->validate([
'file' => [
'bail',
'required',
'max:10000',
function ($attribute, $value, $fail) {
if ($value->getClientMimeType() !== 'text/xml') {
$fail($attribute.'\'s extension is invalid.');
}
},
]
]);
dd('the file is valid');
}
});
Now an image file with the xml extension passes the validation
See using closures for custom validation
It seems that the XML provided by an external company is not respecting the proper XML standard.
As it is not on my hands, I won't reformat it and I will have to manage it as text only. So I guess I can't use a validator in my case.
For those who try to pass xml extension on Laravel 5 (like me).
This will work with other additional extensions also.
Since Laravel ExtensionGuesser allows to add custom guesser via method register we do the folowing.
Make new class with own extensions array. I've made it exdending the original one so it corresponds the interface. I've put it to Helpers folder.
<?php
namespace App\Helpers;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser;
/**
* Provides a best-guess mapping of mime type to file extension.
*/
class PriorExtensionGuesser extends MimeTypeExtensionGuesser
{
/**
* Addition to pretty old map of mime types and their default extensions.
*
* #see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
*/
protected $defaultExtensions = array(
'text/xml' => 'xml',
);
}
In you controller (don't forget use statement):
use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
public function store (Request $request) {
if ($request->hasFile('file')) {
$guesser = ExtensionGuesser::getInstance(); //take the guesser who will guess
$guesser->register(new \App\Helpers\PriorExtensionGuesser()); //add own guesser
$validator = Validator::make($request->all(), [
'file' => 'file|mimes:txt,xls,xlsx,csv,xml|max:32768',
]);
if ($validator->fails()) {
.....
So now guesser checks our array in Prior* class then goes to original one.
I'll need your help there, I have a form when I submit an image, it's working fine, but when I try to display the image on an another page, its display a white square (I can see that it's working because I can see the name of the image in the console).
This is my app.blade.php :
<div class="menu_connect_big_screen">
<img src="{{Auth::user()->image}}"/>
<p>{{Auth::user()->firstName}} {{Auth::user()->lastName}}</p>
Mon compte | Se déconnecter
</div>
And this is my controller :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Auth;
class ProfilePictureController extends Controller
{
public function update(Request $request)
{
$request = $request->All();
User::where('id', Auth::user()->id)
->update(
[
'image' => $request['image']]
);
return redirect()->to('/')->with(['image-changed' => 'Photo de profil modifiée !']);
}
}
I'm kinda new to laravel so any help would be thankful.
Thank you.
If the image is stored in blob you should use base64 in your image tag like so;
<img src="data:image/jpeg;base64,{{base64_encode( Auth::user()->image )}}"/>
However, this is not specific to Laravel.
For example user images stored in public/user_images directory
<div class="menu_connect_big_screen">
<img src="{{ asset('user_images/' . Auth::user()->image) }}" height="50px" width="50px">
<p>{{Auth::user()->firstName}} {{Auth::user()->lastName}}</p>
Mon compte | Se déconnecter
</div>
On my project i made a contact form. It was store details on databse and shows admin panel and sends it to via mail so i cant pass array variables to mailable view.
My controller;
$iletisim = new Contact();
$iletisim->ad = $request->input('ad');
$iletisim->soyad =$request->input('soyad');
$iletisim->email = $request->input('email');
$iletisim->mesaj = $request->input('mesaj');
$iletisim->save();
$gonder = array( 'gonderen'=>$request->input('ad'),
'email'=>$request->input('email'),
'mesaj'=>$request->input('mesaj')
);
Mail::send(new ContactMail($gonder));
Session::flash('success', 'Mesajınız Gönderilmiştir. En kısa sürede dönüş sağlanacaktır.');
return back();
}
My Contact.php
public $bilgiler;
public function __construct($gonder)
{
$this->bilgiler = $gonder;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('homepage.emails.contact')->with(['bilgiler'=>$this->bilgiler]);
}
and my blade file
#component('mail::message')
# New Contact Form
{{$bilgiler->ad}}
Thanks,<br>
{{ config('app.name') }}
#endcomponent
Where is my mistake can you help.
Thanks
First of all, you don't need to add ->with(['bilgiler'=>$this->bilgiler]); since $bilgiger is public property. All public properties of Mailable are available in Blade
Also, since it's an array, you need to access it with:
$bilgiger['gonderen']
The $bilgiler->gonderen syntax is for objects, not for arrays. Also, you don't have id in the array.
And the last thing is you're using markdown email, so use the markdown() method:
return $this->markdown('homepage.emails.contact');
I have saved a file with this command
$newFile = [
'event_id' => $event->id,
'path' => $storePath
];
EventFile::create($newFile);
I can get the path to the file for a link like this:
Storage::disk('public')->url($file->path);
But there is no data about the file size. How can i get the file size in blade view???
Laravel 5^
$request->file('file')->getSize(); // in bytes
Laravel 4
$request->file('file')->getClientSize(); // getClientSize() is deprecated in Laravel 5
The more Simpler way is to use Storage Facade if you have already stored / uploaded file
use Illuminate\Support\Facades\Storage;
public function get_size($file_path)
{
return Storage::size($file_path);
}
Or if you are using S3 Bucket then you can modify the above function like below
use Illuminate\Support\Facades\Storage;
public function get_size($file_path)
{
return Storage::disk('s3')->size($file_path);
}
Check Laravel File Storage
getClientSize() is deprecated starting version 4.1. Use getSize() instead.
https://github.com/symfony/symfony/blob/4.1/UPGRADE-4.1.md#httpfoundation
Very simple(Proper Laravel Way):
//add this at the top of your controller
use File;
// add this with in your function
$size = File::size($PATH_OF_FILE);
laravel 8
$imageSize = $request->file('file')->getSize();
$fil->size = number_format($imageSize / 1048576,2);
$file->size My Table Change It With Your DB Table
According to the Laravel Documentation for version 8.0:
When using the local driver, all files that should be publicly accessible should be placed in the storage/app/public directory.
So the root of your local storage here is the public/ directory within storage/app/
You can Specify the method to get file size in your File Model like this
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class File extends Model
{
use HasFactory;
protected $fillable = [
'name',
'file_path'
];
public function getFileSize()
{
// Ensure $this->file_path begins with '/public/';
return Storage::size($this->file_path);
}
}
And use it like this within your blade file
<div>{{ $file->getFileSize() }}</div>
If you use it this way, $this->file_path must have the format: /public/optional_subdirectory/file_name
I'm developing an app using Laravel 4.2 over HTTPS with secure routes and redirects. I'm using Paginator to paginate results, but the links rendered in the view points to the http pages, how can we force Paginator to generate https links?
I had this issue today and found this global solution.
In your AppServiceProvider::boot method you can add the following to force https on pagination links
$this->app['request']->server->set('HTTPS','on');
If your current page is served over HTTPS, then the pagination URLs generated should use that schema.
However if you're using a proxy that does not pass the correct headers, the Request class responsible for determining if the connection is secure, might not report it as such. To determine if the request is detected as secure use Request::secure(). If that returns false, try using Laravel Trusted Proxies.
If that does not work you can force the pagination URLs with setBaseUrl as follows:
$results->paginate();
$results->setBaseUrl('https://' . Request::getHttpHost() . '/' . Request::path());
Add a custom presenter ZurbPresenter.php in app/helpers/ (you can place it inside other directory provided its path is included in to ClassLoader::addDirectories()):
<?php
class ZurbPresenter extends Illuminate\Pagination\Presenter {
/**
* Get HTML wrapper for a page link.
*
* #param string $url
* #param int $page
* #param string $rel
* #return string
*/
public function getPageLinkWrapper($url, $page, $rel = null)
{
$rel = is_null($rel) ? '' : ' rel="'.$rel.'"';
if (strpos($url, "http://") === 0) {
$url = "https://" . ltrim($url, "http://");
}
return '<li><a href="'.$url.'"'.$rel.'>'.$page.'</a></li>';
}
/**
* Get HTML wrapper for disabled text.
*
* #param string $text
* #return string
*/
public function getDisabledTextWrapper($text)
{
return '<li class="disabled"><span>'.$text.'</span></li>';
}
/**
* Get HTML wrapper for active text.
*
* #param string $text
* #return string
*/
public function getActivePageWrapper($text)
{
return '<li class="active"><span>'.$text.'</span></li>';
}
}
Notice the getPageLinkWrapper() has a logic to replace http by https.
Create a view file to use the presenter. Inside app/views create a file zurb_pagination.php with following content:
<?php
$presenter = new ZurbPresenter($paginator);
$trans = $environment->getTranslator();
?>
<?php if ($paginator->getLastPage() > 1): ?>
<ul class="pager">
<?php
echo $presenter->getPrevious($trans->trans('pagination.previous'));
echo $presenter->getNext($trans->trans('pagination.next'));
?>
</ul>
<?php endif; ?>
Finally change your app config to use the new presenter in app\config/view.php for pagination:
'pagination' => '_zurb_pagination_simple',
I use a similar approach for my website and you can verify it's working here.