Well, I am not sure but what I would have attempted is to follow that path that was designed into Laravel. That is, storing the file in the local storage and linking to public for availability. You can use any disk or directories you want and it has utility methods.
Signature Pad
I'm using this package - https://github.com/szimek/signature_pad
Which allows drawing on screen for signatures etc, it all works, but the file_put_contents() is placing the file in the public directory. But I don't want this I want store it in public/uploads/signatures for example.
$data_uri = $request->signature;
$encoded_image = explode(",", $data_uri)[1];
$decoded_image = base64_decode($encoded_image);
$contents = file_put_contents(sha1($request->session()->get('user.first_name').$request->session()->get('user.last_name')) . "_signature.png", $decoded_image);
The above is what I have currently which obviously return a base64 png file/image but I want to move to the public/uploads/signatures directory then remove from the public directory so I don't have duplicates.
How can one achieve this? I have tried the rename() & move_uploaded_file() functions to no avail.
Thanks @ejdelmonico I'll have a look at this also.
Using the Storage facade I'm getting all kinds of errors like File not found at path:
Did you run the artisan command to link to public? php artisan storage:link
I have now, i'll check again!
Still errors:
I'm using the Storage::move() facade to move it, is that right?
The way it works is that you store the file in local storage (storage folder) Laravel stores it under /storage/app/thefile or you can define that custom directory. After linking for public availability, you can access the file by url. You can use a temp directory and then move/rename the file as needed.
To move you would Storage::move('old/file', 'new/file'). The docs are pretty good for examples.
The file_put_contents() is just storing it within the app/public directory, and I want to move it to app/public/uploads for example
To originally store the file its Storage::put() or one of the other helper methods. That will save it in your local storage and then you can move it.
Yeah tried that also, but nothing is storing.
Keep getting other errors like: file_put_contents(/Users/lee/code/hns/storage/app/public/): failed to open stream: Is a directory
Now adding to the storage

But still not right
Current code based on my last two replies:
$data_uri = $request->signature;
$encoded_image = explode(",", $data_uri)[1];
$decoded_image = base64_decode($encoded_image);
$sig = $request->session()->get('user.first_name').$request->session()->get('user.last_name') . "_signature.png";
$contents = file_put_contents(sha1($request->session()->get('user.first_name').$request->session()->get('user.last_name')) . "_signature.png", $decoded_image);
Storage::put($contents,$sig);
The one in red b95eaeeb... is the actual image that gets stored, but I just want to move that to the uploads/signatures directory
what is the use of linking public/storage to storage/app/public? Why would we want to store files in storage/app/public instead of public/storage or public/uploads?
I dont want to do that I just want to store within public/uploads
how hard could it be to store in public/uploads? I allways store there and it's easy
$contents = file_put_contents(.... is storing in public like the screen shot I posted the b95eaeeb.. red text but I want to move that to the uploads directory.
here is my code that works
if($request->hasFile('file')) {
$album->save();
Session::push('album.hash', $album->hash);
$order = 1;
foreach($request->file('file') as $file){
$rules = array('file' => 'required|mimes:png,gif,jpeg,jpg'); //'mimes:png,gif,jpeg,txt,pdf,doc'
$validator = Validator::make(array('file'=> $file), $rules);
if($validator->passes()){
do{
$imageHash = str_random(7);
} while (Image::where('hash', $imageHash)->withTrashed()->first() != null);
$current = Carbon::now();
$year = $current->year;
$month = $current->month;
$day = $current->day;
$hour = $current->hour;
$folder = 'uploads/'.$year.'/'.$month.'/'.$day.'/'.$hour;
if( ! file_exists($folder)) {
$oldmask = umask(0);
mkdir($folder, 0775, true);
mkdir($folder . '/thumb/', 0775, true);
umask($oldmask);
}
$name = $imageHash .'.'. strtolower($file->getClientOriginalExtension());
$file->move($folder, $name);
take what you need. you do not need file_put_contents, use file->move
ok cool, thanks I'll give it a whirl :)
ok, so I've been having a play around with this:

The image show whats happening: I click that file and it shows this b95eaeeb833a39258fc1c07149d8e4438f71f224_signature.png not the actual image.
The following is the code I have now:
$sig = sha1($request->session()->get('user.first_name').$request->session()->get('user.last_name')) . "_signature.png";
$folder = 'uploads/signatures/';
Storage::put($folder, $sig);
So it's just saving the filename rather than the actual file :( I'm lost....
Hi @theUnforgiven can you share the code you used to implement the whole Signature Pad feature? From the front end to the controller if you don't mind.
I am stuck with the front end still. Thanks
Controller:
/**
* Save Signature
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function saveSignature(Request $request)
{
$user = $request->session()->get('user');
$signature = new Signature;
$signature->user_id = $request->session()->get('user.id');
$signature->position = $request->position;
$data_uri = $request->signature;
$encoded_image = explode(",", $data_uri)[1];
//$decoded_image = base64_decode($encoded_image);
$sig = sha1($request->session()->get('user.first_name').$request->session()->get('user.last_name')) . "_signature.png";
$folder = '/uploads/signatures/';
Storage::put($folder, $sig);
$signature->signature = $encoded_image;
$signature->save();
$request->session()->put('user', $user->load('account', 'signature'));
return back();
}
JS:
$(function () {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var signaturePad = new SignaturePad(document.getElementById('signature-pad'), {
backgroundColor: 'rgba(255, 255, 255, 0)',
penColor: 'rgb(0, 0, 0)'
});
var saveButton = document.getElementById('save');
var cancelButton = document.getElementById('clear');
saveButton.addEventListener('click', function (event) {
if (signaturePad.isEmpty()) {
sweetAlert("Oops...", "Please provide signature first.", "error");
} else {
// do ajax to post it
$.ajax({
url : '/assessments/signature',
type: 'POST',
data : {
signature: signaturePad.toDataURL('image/png'),
position: $('#position').val()
},
success: function(response)
{
sweetAlert("Success!", "Good stuff! Your signature is now saved", "success");
setTimeout(function () {
location.reload();
}, 3000);
//data - response from server
},
error: function(response)
{
sweetAlert("Oops...", "Sorry, something went wrong! We will investigate as soon as possible.", "error");
console.log(response);
}
});
}
});
cancelButton.addEventListener('click', function (event) {
signaturePad.clear();
});
});
Make sure to import the signature JS file before this script.
Thank you a lot. Highly Appreciate it.
@theUnforgiven here is my code if you ever want to save the image in your server... As I can see you are saving it in bits in the database.
$data_uri = $request->signature;
$encoded_image = explode(",", $data_uri)[1];
$decoded_image = base64_decode($encoded_image);
$user = Sentinel::getUser();
$url = 'Signature' . '-id-' . $user->id . '-Name' . $user->first_name . '-' . $user->last_name .'-Rand-' . rand(111,9999).'.png';
$name = 'ID' . $user->id . '-Rand-' . rand(111,9999) . '-' . rand(111,9999) . '-' . rand(111,9999);
$user_id = $user->id;
$data=array(
'user_id' => $user_id,
'name' => $name,
'url' => $url,
);
Signature::insert($data);
file_put_contents('../storage/app/signatures/' . $url, $decoded_image);
Thanks again for your code :) Javascript was a bit painful for me :) :D
Dear sir, i am new in laravel. i want to save signature as png file. Please Guide me
@Bilou, just follow these two pages through and you should be able to get yourself where you need to be.
Hey man do you mind helping me out on how you approach storing the image from the signature pad. Thanks!
@lawkunchi - Sorry I'm a little tied up at the minute, feel free to see the above posts on what I did and also post what you have so far on here and I'll try and help.
I got this error when I try to save the signature : Undefined offset: 1
referring to this line
$encoded_image = explode(",", $data_uri)[1];
@lawkunchi How are you passing the data uri to the form?
Please or to participate in this conversation.