In Laravel 5.3 I'm uploading files like this:
public function upload(Request $request, User $user, $directory)
{
if($request->hasFile('attachment'))
{
$attachments = $request->file('attachment');
foreach ($attachments as $attachment) {
$fileName = $attachment->store('users/' . $user->id . '/' . $directory);
$file = new File;
$file->path = $fileName;
$file->user_id = $user->id;
$this->files()->save($file);
}
}
}
So it's being stored like this:
How do I store a random name (path) instead of a entire path?
(Random unique name something like: 7b11ae012907b5811cb6985d39e16052)
public function upload(Request $request, User $user, $directory)
{
if($request->hasFile('attachment'))
{
$random_name=rand(5, 15);
$attachments = $request->file('attachment');
foreach ($attachments as $attachment) {
$fileName = $attachment->store('users/' . $user->id . '/' . $random_name);
$file = new File;
$file->path = $fileName;
$file->user_id = $user->id;
$this->files()->save($file);
}
}
}
I've done it like this:
public function upload(Request $request, User $user, $directory)
{
if($request->hasFile('attachment'))
{
$attachments = $request->file('attachment');
foreach ($attachments as $attachment) {
$random = str_random(30);
$filename = $random . $attachment->getClientOriginalName();
$attachment->storeAs('users/' . $user->id . '/' . $directory, $filename);
$file = new File;
$file->path = $filename;
$file->user_id = $user->id;
$this->files()->save($file);
}
}
}
Related
I want to upload an image much like a profile image to the project I am working with. I do not want multiple images that can be uploaded simultaneously. The previous image has to delete when a new image is uploaded.
Can anybody help me with this?
I am new to Laravel.
you can use these as reference.
This is for storing the data.
public function store(Request $request)
{
$input = $request->all();
//handle file upload
if ($request->hasFile('partner_img')) {
$fileNameWithExt = $request->file('partner_img')->getClientOriginalName();
$filename = pathinfo($fileNameWithExt, PATHINFO_FILENAME);
$extension = $request->file('partner_img')->getClientOriginalExtension();
$partner_img = $filename . '_' . time() . '.' . $extension;
$path = $request->file('partner_img')->move('images/partners', $partner_img);
$input['partner_img'] = $partner_img;
} else {
$package_img = 'noimage.jpg';
}
$partner = $this->partnerRepository->create($input);
Flash::success('Partner saved successfully.');
return redirect(route('partners.index'));
}
this is for updating.
public function update($id, Request $request)
{
$input = $request->all();
$partner = $this->partnerRepository->findWithoutFail($id);
if (empty($partner)) {
Flash::error('Partner not found');
return redirect(route('partners.index'));
}
if ($request->hasFile('partner_img')) {
$fileNameWithExt = $request->file('partner_img')->getClientOriginalName();
$filename = pathinfo($fileNameWithExt, PATHINFO_FILENAME);
$extension = $request->file('partner_img')->getClientOriginalExtension();
$new_partner_img = $filename . '_' . time() . '.' . $extension;
$path = $request->file('partner_img')->move('images/partners', $new_partner_img);
Storage::delete('partners/'.$partner->partner_img);
$input['partner_img']= $new_partner_img;
}
$partner = $this->partnerRepository->update($input, $id);
Flash::success('Partner updated successfully.');
return redirect(route('partners.index'));
}
I did it this way along with some other fields. Now it is solved:
public function update(Request $request)
{
request()->validate([
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'file' => 'required|max:100000|mimes:doc,docx,pdf',
'email' => 'required|email',
]);
$peoples = People::find($request->id);
$peoples->Name = $request->name;
$peoples->Email = $request->email;
$peoples->Address = $request->address;
if ($request->hasFile('image')) {
if ($peoples->image) {
File::delete(public_path($peoples->image));
}
$imageName = time() . '.' . request()->image->getClientOriginalExtension();
request()->image->move(public_path('images/'), $imageName);
$peoples->image = $imageName;
}
if ($request->hasFile('file')) {
if ($peoples->File) {
File::delete(public_path($peoples->File));
}
$fileName = time() . '.' . request()->file->getClientOriginalExtension();
request()->file->move(public_path('files/'), $fileName);
$peoples->File = $fileName;
}
$peoples->update();
$peoples->save();
}
I use laravel 4.2, because this project has been around for years. :)
Now, how can i replace and delete previous files uploaded in public
directory, when edit a record ?
Given the following Controller code ( Update Methode ) :
public function update($id)
{
$idd = Sentry::getUser()->id;
try {
$validator = Validator::make(
Input::all(),
array(
'first_name' => 'required',
'last_name' => 'required',
'eng_certificate' => 'image|mimes:png,jpeg,jpg|max:1100',
'profile_img' => 'image|mimes:png,jpeg,jpg|max:1100',
)
);
if ($validator->passes()) {
$profile = User::find($id);
$profile->first_name = Input::get('first_name');
$profile->last_name = Input::get('last_name');
if (Evidence::where('user_id', $idd)->count() == 0) {
$evidence = new Evidence;
$evidence->user_id = $idd;
$evidence->created_at = jDate::forge()->time();
} else {
$evidence = Evidence::where('user_id', $idd)->first();
$evidence->updated_at = jDate::forge()->time();
}
if (Input::hasFile('eng_certificate')) {
$image = Input::file('eng_certificate');
$destinationPath = 'uploads/evidence';
$filename = $image->getClientOriginalName();
$extension = $image->getClientOriginalExtension();
$image_filename = sha1($filename) . '-' . rand(0, 1000) . '.' . $extension;
$image_uploadSuccess = $image->move($destinationPath, $image_filename);
if ($image_uploadSuccess) {
$evidence->eng_certificate = $image_filename;
$evidence->save();
}
}
if (Input::hasFile('profile_img')) {
$image = Input::file('profile_img');
$destinationPath = 'uploads/evidence/profile_img/';
$filename = $image->getClientOriginalName();
$extension = $image->getClientOriginalExtension();
$image_filename = sha1($filename) . '-' . rand(0, 1000) . '.' . $extension;
$image_uploadSuccess = $image->move($destinationPath, $image_filename);
if ($image_uploadSuccess) {
$evidence->profile_img = $image_filename;
$evidence->save();
}
}
$profile->save();
return Redirect::route('cpanel.home')->with('success', 'اطلاعات پروفایل شما با موفقیت بروز گردید.');
}
else {
return Redirect::back()->withInput()->withErrors($validator->messages());
}
}
catch (LoginRequiredException $e) {
return Redirect::back()->withInput()->with('danger', $e->getMessage());
}
}
How can I fix it?
Thank you.
find out current file location
use php unlink function
https://www.w3schools.com/php/func_filesystem_unlink.asp
You can interact with the filesystem by using: Laravel Filesystem
For example:
Storage::delete('file.jpg');
See: https://laravel.com/docs/5.8/filesystem#deleting-files
I'm using flysystem to work with my files.
I don't see an easy way to flatten a directory so I used this
public function flattenDir($dir, $destination = null) {
$files = find($dir . '/*');
foreach ($files as $file) {
$localdir = dirname($file);
if (!isDirectory($file)) {
$destination = $dir . '/' . basename($file);
move($file, $destination);
}
if (isDirectory($localdir) && isEmptyDirectory($localdir) && ($localdir != $dir)) {
remove($localdir);
}
}
}
Is there an easier way by using flysystem?
I finally used that. It also manage a few things that I needed
I'm using flysystem mount manager but this script could be easily adapted to work with the default flysystem instance.
$elements should be the result of manager->listContents('local://my_dir_to_flatten');
And $root is a string my_dir_to_flatten in my case.
public function flatten($elements , $root) {
$files = array();
$directories = array();
//Make difference between files and directories
foreach ($elements as $element) {
if( $element['type'] == 'file' ) {
array_push($files, $element);
} else {
array_push($directories, $element);
}
}
//Manage files
foreach ($files as $file) {
//Dont move file already in root
if($file['dirname'] != $root) {
//Check if filename already used in root directory
if ( $this->manager->has('local://'.$root . '/' . $file['basename']) ) {
//Manage if file don't have extension
if( isset( $file['extension']) ) {
$file['basename'] = $file['filename'] . uniqid() . '.' . $file['extension'];
} else {
$file['basename'] = $file['filename'] . uniqid();
}
}
//Move the file
$this->manager->move('local://' . $file['path'] , 'local_process://' . $root . '/' . $file['basename']);
}
}
//Delete folders
foreach ($not_files as $file) {
$this->manager->deleteDir( 'local://' . $file['path'] );
}
}
Finally I can upload and move the images, but now I want to create a multiple upload images on Laravel. Is that possible? Did I have to use array to make it?
Can I just modify a little bit from this code?
It's on my ProductController.php
$picture = '';
if ($request->hasFile('images')) {
$file = $request->file('images');
$filename = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$picture = date('His').$filename;
$destinationPath = base_path() . '\public\images/';
$request->file('images')->move($destinationPath, $picture);
}
if (!empty($product['images'])) {
$product['images'] = $picture;
} else {
unset($product['images']);
}
Thank you.
Note: My code above is from a kindhearted person on stackoverflow, thanks again ;)
At your frontend form you'll have to use your field attribute name like
name="images[]"
And your controller code would be like this.
$picture = '';
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach($files as $file){
$filename = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$picture = date('His').$filename;
$destinationPath = base_path() . '\public\images';
$file->move($destinationPath, $picture);
}
}
if (!empty($product['images'])) {
$product['images'] = $picture;
} else {
unset($product['images']);
}
Your input from $_POST will be coming in as an array. All you need to do is to iterate through it:
$picture = '';
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach($files as $file){
$filename = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$picture = date('His').$filename;
$destinationPath = base_path() . '\public\images/';
$request->file('images')->move($destinationPath, $picture);
}
}
Slight modified code to upload multiple image.
public function store(Request $request)
{
$pid = $request->input('pid');
$input = $request->file('images');
$picture = array();
if($request->hasFile('images')) :
foreach ($input as $item):
$extension = $item->getClientOriginalName();
$name = date('Ymd') . '.' . $extension;
$destinationPath = base_path() . '/uploads/images/';
$item->move($destinationPath, $name);
$arr[] = $name;
endforeach;
$picture = implode(",", $arr);
else:
$picture = '';
endif;
DB::table('document')->insert(array('pid' => $pid,'image' => $picture));
Session::flash('message', 'Multiple pictures are uploaded successfully');
return redirect('/image-upload');
}
In my server I have folders and sub-directory
I want to call a flatten methode to a directory to move every files at the same level and remove all empty folders
Here is what i've done so far:
public function flattenDir($dir, $destination=null) {
$files = $this->find($dir . '/*');
foreach ($files as $file) {
if(!$destination){
$destination = $dir . '/' . basename($file);
}
if (!$this->isDirectory($file)) {
$this->move($file, $destination);
}else{
$this->flattenDir($file, $destination);
}
}
foreach ($files as $file) {
$localdir = dirname($file);
if ($this->isDirectory($localdir) && $this->isEmptyDirectory($localdir) && ($localdir != $dir)) {
$this->remove($localdir);
}
}
}
public function find($pattern, $flags = 0) {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
$files = array_merge($files, $this->find($dir . '/' . basename($pattern), $flags));
}
return $files;
}
This code dont show any error on run, but the resukt is not as expected.
For exemple if I have /folder1/folder2/file I want to have /folder2/file as a result but here the folders still like they where ...
I finally make my code works, I post it here in case it help someone
I simplified it to make it more efficient. By the way this function is part of a filemanager classe I made, so I use function of my own class, but you can simply replace $this->move($file, $destination); by move($file, $destination);
public function flattenDir($dir, $destination = null) {
$files = $this->find($dir . '/*');
foreach ($files as $file) {
$localdir = dirname($file);
if (!$this->isDirectory($file)) {
$destination = $dir . '/' . basename($file);
$this->move($file, $destination);
}
if ($this->isDirectory($localdir) && $this->isEmptyDirectory($localdir) && ($localdir != $dir)) {
$this->remove($localdir);
}
}
}