Laravel displaying base64 image - php

How can I send e-mail with attached image if I receive the data in base64 format?
Here is mail template:
<h1>You got mail from - {{$user->name}}</h1>
<h2>Date:</h2>
<p>{{$post->created_at}}</p>
<h2>Message:</h2>
<p>{{$post->body}}</p>
<img src="data:image/png;base64, {{$image}}">
<div>
</div>
And the logic:
public function createPost()
{
$user = JWTAuth::toUser();
$user->posts()->create(['user_id' => $user->id, 'body' => Input::get('comment.body')]);
Mail::send('mail.template', [
'image' => Input::get('image'),
'user' => $user,
'post' => Post::where('user_id', $user->id)->get()->last(),
], function ($m) use ($user) {
$m->from('xyz#app.com', 'XYZ');
$m->to('xyz#gmail.com', $user->name)->subject('Subject');
});
}
From this I only get mail with full base64 string...img tag gets ignored

Attachments
To add attachments to an email, use the attach method within the
mailable class' build method. The attach method accepts the full path
to the file as its first argument:
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attach('/path/to/file');
}
More information here (for Laravel 5.3).
I hope, it will be helpful.

The solution I came up with is to save the image first in order to attach it as Viktor suggested although I don't have Laravel 5.3. so the method is somehow different.
User may or may not send the picture, so the method is as follows:
$destinationPath = null;
if($request->has('image')){
// save received base64 image
$destinationPath = public_path() . '/uploads/sent/uploaded' . time() . '.jpg';
$base64 = $request->get('image');
file_put_contents($destinationPath, base64_decode($base64));
}
And then attach the saved image to the mail:
Mail::send('mail.template', [
'user' => $user,
'post' => Post::where('user_id', $user->id)->get()->last(),
], function ($m) use ($user) {
$m->from('xyz#app.com', 'XYZ');
$m->to('xyz#gmail.com', $user->name)->subject('Subject');
if($request->has('image')){
$m->attach($destinationPath);
}
});
The mail template:
<h1>You got mail from - {{$user->name}}</h1>
<h2>Date:</h2>
<p>{{$post->created_at}}</p>
<h2>Message:</h2>
<p>{{$post->body}}</p>

Related

How to POST data on database using Postman with laravel 9

I try to POST data to database with "form-data" on "postman" with Laravel 9, and I try to return the data to JSON.
This is my controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\M_Barang;
class Utama extends Controller
{
public function index() {
return view('Utama');
}
public function store(Request $request) {
$this->validate($request, [
'file' => 'required|max:2048'
]);
$file = $request->file('file');
$nama_file = time()."_".$file->getClientOriginalName();
$tujuan_upload = 'data_file';
if ($file->move($tujuan_upload,$nama_file)) {
$data = M_Barang::create([
'nama_produk' => $request->nama_produk,
'harga' => $request->harga,
'gambar' => $nama_file
]);
$res['message'] = "succsess!";
$res['values'] = $data;
return response($res);
}
}
}
I get the following result:
This is my expected result:
You need to send data from raw section in JSON Format, and try to send your image in base64 format (because its very convenient way to store a image into file system via the API).
Example:{"profile_pic":"data:image/png;base64,iVBORw0KGgoAAAANSUh (base64 image string)"}
you can convert base64 image here https://www.base64-image.de/
and in Android and iOS has some libraries for converting image to base 64 while sending data to API
Welcome in Advance.
In Postman's headers section, you have to set Accept and content-type to application/json:
Image

How can I send an email with a PDF with Laravel

I have a PDF coded in base 64, it is an attribute in my database, and I send emails through Laravel but I do not know how can I send the base64 as a PDF.
public function toMail()
{
$pdf_decoded = base64_decode($this->table->raw_label);
$message = (new MailMessage)
->subject(env('APP_NAME').' - HI #'. $this->order->id)
->greeting('¡Hi!');
if(env('APP_URL') == 'http://test.test'){
$message->bcc(['test#test.com']);
}
return $message;
}
I know attach property, but I do not know hot to implement it.
You can actually do this through the Mail or Notification class, personally I would use a Notification but it's up to you. Just use the ->attach($pathToFile) method and give it the file path as a parameter.
Here's an example using a Notification, hope this helps!
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('Please download the PDF.')
->attach(public_path($this->filename), [
'as' => 'filename.pdf',
'mime' => 'text/pdf',
]);
}

"Unable to open file for reading" (Swift_IoException) in Laravel Mailable

I'm trying to use Mailable in Laravel.
In developing a new Mailable, I have everything working except attaching an EXISTING file to the mailable.
An error returns as such:
"message": "Unable to open file for reading [/public/storage/shipments/CJ2K4u6S6uluEGd8spOdYgwNkg8NgLFoC6cF6fm5.pdf]",
"exception": "Swift_IoException",
"file": "E:\\webserver\\htdocs\\truckin\\vendor\\swiftmailer\\swiftmailer\\lib\\classes\\Swift\\ByteStream\\FileByteStream.php",
"line": 131,
But if you go through the folders and files, there is in fact a file there and I can open it, I can even open it through an ajax popup to view details.
Here is my mailable:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Shipment;
use App\Shipment_Attachment;
class shipmentAttachments extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public $shipment, $attachment, $storagePath;
public function __construct($shipment, $attachment, $storagePath)
{
$this->shipment = $shipment;
$this->attachment = $attachment;
$this->attachmentFile = '/public'.$storagePath;
$this->proNumber = $shipment->pro_number;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('billing#cmxtrucking.com')
->cc('billing#cmxtrucking.com')
->subject('New Attachment(s) - '. $this->proNumber)
->view('emails.shipments.shipmentAttachments',['shipment'=> $this->shipment])
->attach($this->attachmentFile);
}
}
And here is my controller that leads to the mailable:
public function attachmentsEmail(Request $request){
$shipment = Shipment::findOrFail($request->shipmentID);
$attachment = Shipment_Attachment::findOrFail($request->attachmentID);
$storagePath = Storage::url($attachment->attachmentPath);
$email = $request->email;
Mail::to($email)->send(new shipmentAttachments($shipment, $attachment, $storagePath)); //maybe try to use queue instead of send...
return back();
}
So I'm not sure where this could be coming from.
Try to use public_path() laravel helper function instead of '/public'.
$this->attachmentFile = public_path() . '/' . $storagePath;
Maybe you need to change this variable in public/index.php. I have right below the require bootstrap:
$app->bind('path.public', function() {
return __DIR__;
});
Make some tests.
dd(public_path());
dd(public_path() . '/' . $storagePath);
Or maybe verify if file exist with FileSystem class.
Hope this help you!
I was serching a lot about that, it happens the same when you are tryng to build a PDF on dompdf, just exactly the same, you normaly could write this:
('/image/'.$file) and will not work , so you can solve it adding a dot just behind the rout ".", just like this:
('./image/'.$file)
It works when you want to add a attach in a mail sending or when you want to make a PDF including images in it.
If you use Storage, and you are trying to export xlsx files, using Laravel Notifications:
in your notification class:
public function toMail($notifiable) {
$path = Storage::disk('export')->getAdapter()->getPathPrefix();
return (new MailMessage)
->greeting(language_data('Your file is ready', $this->user->language_id).$this->user->name)
->line(language_data('Please, check your Email attachments.', $this->user->language_id))
->subject(language_data('Export Contacts', $this->user->language_id))
->attach($path.$notifiable->filename, [ 'as' => $notifiable->filename, 'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ])
->line(language_data('If you did not request this file, please contact us.', $this->user->language_id));
}
It works fine for me.
Instead of /public we have to use laravel's helper function public_path()
then concatenate actual file path. otherwise the attachment file operation will not work
so your updated code should be like:-
$this->attachmentFile = public_path() . '/' . $storagePath;
Most of these errors occur in larval on Ubuntu (Linux).
It may be skipped in some cases of windows.

How to test file upload with laravel and phpunit?

I'm trying to run this functional test on my laravel controller. I would like to test image processing, but to do so I want to fake image uploading. How do I do this? I found a few examples online but none seem to work for me. Here's what I have:
public function testResizeMethod()
{
$this->prepareCleanDB();
$this->_createAccessableCompany();
$local_file = __DIR__ . '/test-files/large-avatar.jpg';
$uploadedFile = new Symfony\Component\HttpFoundation\File\UploadedFile(
$local_file,
'large-avatar.jpg',
'image/jpeg',
null,
null,
true
);
$values = array(
'company_id' => $this->company->id
);
$response = $this->action(
'POST',
'FileStorageController#store',
$values,
['file' => $uploadedFile]
);
$readable_response = $this->getReadableResponseObject($response);
}
But the controller doesn't get passed this check:
elseif (!Input::hasFile('file'))
{
return Response::error('No file uploaded');
}
So somehow the file isn't passed correctly. How do I go about this?
For anyone else stumbling upon this question, you can nowadays do this:
$response = $this->postJson('/product-import', [
'file' => new \Illuminate\Http\UploadedFile(resource_path('test-files/large-avatar.jpg'), 'large-avatar.jpg', null, null, null, true),
]);
UPDATE
In Laravel 6 the constructor of \Illuminate\Http\UploadedFile Class has 5 parameters instead of 6. This is the new constructor:
/**
* #param string $path The full temporary path to the file
* #param string $originalName The original file name of the uploaded file
* #param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream
* #param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
* #param bool $test Whether the test mode is active
* Local files are used in test mode hence the code should not enforce HTTP uploads
*
* #throws FileException If file_uploads is disabled
* #throws FileNotFoundException If the file does not exist
*/
public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, $test = false)
{
// ...
}
So the above solution becomes simply:
$response = $this->postJson('/product-import', [
'file' => new \Illuminate\Http\UploadedFile(resource_path('test-files/large-avatar.jpg'), 'large-avatar.jpg', null, null, true),
]);
It works for me.
Docs for CrawlerTrait.html#method_action reads:
Parameters
string $method
string $action
array $wildcards
array $parameters
array $cookies
array $files
array $server
string $content
So I assume the correct call should be
$response = $this->action(
'POST',
'FileStorageController#store',
[],
$values,
[],
['file' => $uploadedFile]
);
unless it requires non-empty wildcards and cookies.
The best and Easiest way : First Import the Necessary things
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
Then make a fake file to upload.
Storage::fake('local');
$file = UploadedFile::fake()->create('file.pdf');
Then make a JSON Data to pass the file. Example
$parameters =[
'institute'=>'Allen Peter Institute',
'total_marks'=>'100',
'aggregate_marks'=>'78',
'percentage'=>'78',
'year'=>'2002',
'qualification_document'=>$file,
];
Then send the Data to your API.
$user = User::where('email','candidate#fakemail.com')->first();
$response = $this->json('post', 'api/user', $parameters, $this->headers($user));
$response->assertStatus(200);
I hope it will work.
With phpunit you can attach a file to a form by using attach() method.
Example from lumen docs:
public function testPhotoCanBeUploaded()
{
$this->visit('/upload')
->name('File Name', 'name')
->attach($absolutePathToFile, 'photo')
->press('Upload')
->see('Upload Successful!');
}
Here is a full example how to test with custom files. I needed this for parsing CSV files with known format so my files had to had exact formatting and contents. If you need just images or random sized files use $file->fake->image() or create() methods. Those come bundled with Laravel.
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
class PanelistImportTest extends TestCase
{
/** #test */
public function user_should_be_able_to_upload_csv_file()
{
// If your route requires authenticated user
$user = Factory('App\User')->create();
$this->actingAs($user);
// Fake any disk here
Storage::fake('local');
$filePath='/tmp/randomstring.csv';
// Create file
file_put_contents($filePath, "HeaderA,HeaderB,HeaderC\n");
$this->postJson('/upload', [
'file' => new UploadedFile($filePath,'test.csv', null, null, null, true),
])->assertStatus(200);
Storage::disk('local')->assertExists('test.csv');
}
}
Here is the controller to go with it:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
class UploadController extends Controller
{
public function save(Request $request)
{
$file = $request->file('file');
Storage::disk('local')->putFileAs('', $file, $file->getClientOriginalName());
return response([
'message' => 'uploaded'
], 200);
}
}
Add similar setUp() method into your testcase:
protected function setUp()
{
parent::setUp();
$_FILES = array(
'image' => array(
'name' => 'test.jpg',
'tmp_name' => __DIR__ . '/_files/phpunit-test.jpg',
'type' => 'image/jpeg',
'size' => 499,
'error' => 0
)
);
}
This will spoof your $_FILES global and let Laravel think that there is something uploaded.

Localization in emails with Laravel 5

I'm new to Laravel and trying to send an e-mail after a user signed up via a form. I'm using the default authentication files shipped with Laravel and modified them. For example: I want only to require an unique emailadress for registration, then send the credentials and automaticly login the new user.
For maybe future purposes I'm also working with the language files where I store my translations.
I've customized the AuthController to also accept a MailerContract and within the postRegistration function I'm sending the e-mail like below:
/**
* Handle a registration request for the application.
*
* #param \Illuminate\Foundation\Http\FormRequest $request
* #return \Illuminate\Http\Response
*/
public function postRegister(Request $request)
{
$validator = $this->registrar->validator($request->all());
if ($validator->fails())
{
$this->throwValidationException(
$request, $validator
);
}
$input = $request->all();
$input['password'] = str_random(8);
$this->auth->login($this->registrar->create($input));
$this->mailer->send('emails.welcome', ['email' => $input['email'], 'password' => $input['password']], function($message) use($input) {
$message->to($input['email'])->subject(trans('emails.welcome:subject'));
});
return redirect($this->redirectPath());
}
I've noticed that my subject-value is not translated. How to use language files in the Controllers/Traits? Doesn't Laravel pick this up from the view?
As asked, a part of the language file: (/resources/lang/nl/emails.php)
<?php
return [
'welcome:subject' => 'Uw inloggegevens' // Dutch for Your login credentials
];
You need to use multidimensional arrays in /resources/lang/nl/emails.php:
return [
'welcome' => [
'subject' => 'Uw inloggegevens',
],
];
And use dot notation instead of colon in the trans function:
$message->to($input['email'])->subject(trans('emails.welcome.subject'));
I ran into another thing with localization and asked a question about that on SO. Seems like using a middleware is the solution to this, because that sets the correct language in the app.
With thanks to #lukasgeiter, the answer can be found here: Localization with Laravel5 without domain.com/language/

Categories