How to upload base64 encoded image and other image types with Laravel
I am going to be really straight to the point on this one. If you need to upload a base64 encoded image or you just want to learn how to do it for future use, then bookmark this page now.
I won’t talk about the User Interface or the input form. I will only talk about the actual method within your controller. I will assume you have that part covered already and your are building a RESTful API. So let’s call the method UploadImage
What does this method do? 🤓
The method uploads multiple image types, such as: jpeg, png, svg, gif and base64 encoded images. So it handles all our image upload needs 🏌🏼♂️
👶🏼Baby steps… Start by declaring the method
public function UploadImage(Request $request) {
//method body goes here
}
Some thoughts about the process 🤔
Because we expect the method to receive and handle both multi-part form data and json string data, we need to prepare for that. What i mean here is that you need to…
Ensure you send data from your client(AXIOS, SuperAgent, Fetch, HttpClient, etc) as multi-part form data for files other base64 or as a json object with the base64 as key-value pair.
For images with jpeg, gif, svg or png extensions, we should expect them as files ($_FILES). For base64 encoded images, we should expect json key-value pair with the base64 encoded image as the value.
Ok let’s write more code. to handle both cases: base64 image and other image types
public function UploadImage(Request $request) {
if ($request->hasFile('photo')){
//handle jpeg,svg,png image types here //this check assumes your client sends the image with the key photo
} else {
//handle base64 encoded images here
}
}
Here’s the complete code for uploading other image types apart from base64 encoded images.
public function UploadImage(Request $request) { if ($request->hasFile('photo')){
//handle jpeg, jpg, svg, png image types here
//this check assumes your client sends the image with the key photo //validate request $this->validate($request,[ 'photo' => 'required|file|image|mimes:jpeg,png,gif,svg' ]); $file = $request->file('photo');
//create a filename $filename = time().'_'.$file->getClientOriginalName() .".".$file->getClientOriginalExtension(); //upload the image as a stream to save memory while uploading $response =
Storage::putFileAs('images',$file,Str::slug($filename)); //return a response as json assuming you are building a restful API return response()->json([ 'message'=>'File uploaded', 'data'=> ['file'=>$response] ]);
} else {
//handle base64 encoded images here
}
}
A few points to notes here.
Here we use the putFileAs
as method on the Storage facade so we don't run out memory while uploading the image. Laravel has some built in optimisation in this method. It basically uses the fopen
built-in PHP function for opening the file to be uploaded as a stream instead of loading the entire file to memory while it moves it to the disk.
It also closes the file opened using fclose
after upload is successful or fails to avoid memory leaks.
Here’s the code for uploading base64 encoded image to local storage or directly to the server
public function UploadImage(Request $request) {
if ($request->hasFile('photo')){
//handle jpeg, jpg, svg, png image types here
//this check assumes your client sends the image with the key photo } else {
//handle base64 encoded images here
$name = Str::random(15).'.png';
Storage::put($name, $request->input('photo'));
//return a response as json assuming you are building a restful API return response()->json([ 'message'=>'File uploaded', 'data'=> ['file'=>$response] ]);
}
}
Here’s the code for uploading base64 encoded image to remote storage like AWS S3 and others
public function UploadImage(Request $request) {
if ($request->hasFile('photo')){
//handle jpeg,svg,png image types here
//this check assumes your
//client sends the image with the key photo
} else {
//handle base64 encoded images here
$name = Str::random(15).'.png'; // decode the base64 file
$file = base64_decode( preg_replace('#^data:image/\w+;base64,#i', '', $request->input('photo')
)); Storage::put($name, $file);Storage::put($name, $file);
//to stream the upload with putFileAs or putFile,
//a resource of Illuminate\Http\File or //Illuminate\Http\UploadedFile type is required$file = new File(public_path($name));
$response = Storage::disk('s3')
->putFileAs('images',$file,$name); if ($response){
//clean up local storage before response
Storage::delete($name);
return response()->json(
['message'=>'File uploaded',
'data'=> ['file'=> $response]
]);
}else {
return response()->json(['message'=>'Error uploading File', 'data'=> ['file'=> $response]], 400);
} }
}
Uploading as a stream to a remote storage requires direct access to the resource being uploaded.
In the case of uploading base64 encoded file from a remote client, like using Fetch in a mobile application, what is sent over to the server is base64 string, so we need to first upload the file on the local server and stream it over to the remote storage. I know this doesn’t sound sustainable, so if you have a better implementation you can drop your comments below.
Follow me on Linkedin : https://www.linkedin.com/in/victor-ighalo/