So your filename should be /storage/imagename.png for instance ?
Symlink over SSH Sharedhosting
Hey guys, I have a website on a shared hosting provider. But my file upload doesn't work properly. The file is successfully uploaded to the folder storage/app/public/uploads but it doesn't show on my site if I call the file. On localhost everything works fine
What I did to deploy the website is.
Login over SSH:
-git pull my project
-install everything necessary
and then I ran
php artisan storage:link
in my Laravel project folder.
My public folder is still inside the laravel folder as default. Nothing changed from the folder structure. In the option of the web host I set the target folder of the domain to the laravelproject/public.
When I log in via FTP everything seems fine. When I click on the storage folder in public it redirects me to storage/app/public.
Does anyone know why this can happen? Could it be that symlinks are deactivated on this shared hosting server? And if yes what would be the alternative that is secure.
my controller looks like this
if($request->hasFile('image')){
//Get filename with the extension
$filenameWithExt = $request->file('image')->getClientOriginalName();
//Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
//Get just ext
$extension = $request->file('image')->getClientOriginalExtension();
//Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
//Upload Image
$path = $request->file('image')->storeAs('public/uploads', $fileNameToStore);
}
else
{
$fileNameToStore = 'noimage.jpg';
}
$post->image = $fileNameToStore;
$post->save();
And I try to view the file with
<a><img style="width:100%" onclick="test()" id="{{$post->id}}"class="z-depth-1 img-thumbnail" src="./storage/uploads/{{$post->image}}" alt="video"
data-toggle="modal" data-target="#modal-{{$post->id}}"></a>
so yes file is named storage/upload/imagename.png
remove the dot in
src="./storage/uploads/{{$post->image}}"
check the generated src in the browser source and check if you can get the file by pasting the url into the address bar.
Note this will NOT work correctly if you can see /public/ in your URL
The way you installed, you should check your .env file to make sure it's not exposed.
Why would you need a symlink, you could just put images under public_html ( an image folder).
Use asset helper to serve them.
Did you properly install laravel above public_html.
@snapey removing the dot didn't change anything. The link in the browser is src="/storage/uploads/chip_1585082904.jpg" and if I pas the link in the browser I get the error:
Server Error
403
Forbidden
You do not have permission to access this document.
@jlrdw why would my .env file be exposed? My Laravel project is over the folder public. MyProject/public -> here is where I linked the hosting to look for the index.html
And on localhost everything works fine. Pushed it to git and installed everything on the webserver. Same folder structure.
Everything sounds ok, but the error you are getting is presumably direct from your web server, not generated by laravel
The only thing I can suggest is check your permissions. The public storage folder should have read only permission
@jlrdw the reason people write images into storage folder (and then symlink it to the outside) is so that you then don't need to give the web server any permission to write to any external facing folders. Yes files can be saved directly on the public side, but you have to then give write permissions
@snapey Symlinks are not allowed on the server that why I am now trying to upload the file directly to the public path. But if i use
$path = $request->file('image')->storeAs('public/uploads', $fileNameToStore);
it always stores the file in the storage folder even if I change the disks to something like this.
'disks' => [
'local' => [
'driver' => 'local',
'root' => public_path('app'),
],
'public' => [
'driver' => 'local',
'root' => public_path('app/public'),
'url' => env('APP_URL').'/public',
'visibility' => 'public',
],
How should my function and disk looks like if i want to use the
storeAs function?
From the docs
If you do not want a file name to be automatically generated, you may use the storeAs method, which accepts the path, file name, and disk name as its arguments:
$path = $request->file('image')->storeAs('uploads', $fileNameToStore, 'public');
but your public disk definition seems wrong also
I would expect more like
'public' => [
'driver' => 'local',
'root' => public_path(),
'url' => env('APP_URL'),
'visibility' => 'public',
],
hmm it still uploads in the storage folder. Maybe I need to clear the cash or something? The upload lands in storage/app/public/uploads if I use
$path = $request->file('image')->storeAs('uploads', $fileNameToStore, 'public');
'public' => [
'driver' => 'local',
'root' => public_path(),
'url' => env('APP_URL'),
'visibility' => 'public',
],
what I found is this : https://stackoverflow.com/questions/44577380/how-to-upload-files-in-laravel-directly-into-public-folder
But when I create a new disk and try to use it with
storeAs('uploads', $fileNameToStore, 'public');
I get the error
Disk [public_uploads] does not have a configured driver.
New disk
'public_uploads' => [
'driver' => 'local',
'root' => public_path() . '/uploads',
],
new function
$path = $request->file('image')->storeAs('', $fileNameToStore,'public_uploads');
Edit: found https://laracasts.com/discuss/channels/laravel/image-upload-using-storage-function-to-public-folder Will try
Edit2: For me worked
$request->file('photo')->move(public_path("/uploads"), $newfilename);
Just make a constant something like:
define('ASSET', realpath(dirname(__FILE__)). DS . 'assets' . DS);
And when uploading:
// code for request etc etc
$destinationPath = ASSET . 'upload/imgdogs';
// more upload code etc etc
// then
$file->move($destinationPath, $newname);
I.e.,
if (isset($_POST['submit'])) {
$lid = DB::table('dc_dogs')->count();
$lid = $lid + 1;
$file = Request::file('ufile');
$file_name = $file->getClientOriginalName();
$file_ext = $file->getClientOriginalExtension();
$fileInfo = pathinfo($file_name);
$filename = $fileInfo['filename'];
$newname = $filename . $lid . "." . $file_ext;
$destinationPath = ASSET . 'upload/imgdogs';
$file->move($destinationPath, $newname);
$dogpic = $newname;
$dogname = ucfirst(Request::input('dogname'));
$sex = ucfirst(Request::input('sex'));
$comments = Request::input('comments');
$adopted = !empty(Request::input('adopted')) ? '1' : '0';
$lastedit = date("Y-m-d H:i:s");
$postdata = array(
'dogpic' => $dogpic,
'dogname' => $dogname,
'sex' => $sex,
'comments' => $comments,
'adopted' => $adopted,
'lastedit' => $lastedit
);
DB::table('dc_dogs')->insert($postdata);
}
Never had an issue with that, never no error, never no problem, but validate as needed.
Edit: You have to define DS
defined('DS') || define('DS', DIRECTORY_SEPARATOR);
Saves having to type DIRECTORY_SEPARATOR every time.
I found a short answer to the problem just move the file to the public with
$request->file('photo')->move(public_path("/uploads"), $newfilename);
There you go. How are you ensuring unique names.
$filenameWithExt = $request->file('image')->getClientOriginalName();
//Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
//Get just ext
$extension = $request->file('image')->getClientOriginalExtension();
//Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
My first post =D
@pain12 If you would and don't mind, show your complete code, I will bookmark to help others in the future.
May questions come up on image uploading.
My whole function looks like this. Just that the validation message doesn't work.
public function store(Request $request)
{
$rules = array(
'title' => 'required',
'body' => 'required',
'image' => 'file|image|nullable|max:5000',
'monday' => 'required_without_all:tuesday,wednesday,thursday,friday,saturday,sunday,immer',
'tuesday' => 'required_without_all:monday,wednesday,thursday,friday,saturday,sunday,immer',
'wednesday' => 'required_without_all:monday,tuesday,thursday,friday,saturday,sunday,immer',
'thursday' => 'required_without_all:monday,tuesday,wednesday,friday,saturday,sunday,immer',
'friday' => 'required_without_all:monday,tuesday,wednesday,thursday,saturday,sunday,immer',
'saturday' => 'required_without_all:monday,tuesday,wednesday,thursday,friday,sunday,immer',
'sunday' => 'required_without_all:monday,tuesday,wednesday,thursday,friday,saturday,immer',
'immer' => 'required_without_all:monday,tuesday,wednesday,thursday,friday,saturday,sunday'
);
$message = array(
'title.required' => 'The :attribute field is required.');
// 'title' => 'Titel benötigt' ,
// 'body' => 'link benötigt',
// 'image' => '',
// 'monday' => 'test',
// 'tuesday' => 'test',
// 'wednesday' => 'test',
// 'thursday' => 'test',
// 'friday' => 'test',
// 'saturday' => 'test',
// 'sunday' => 'test',
// 'immer' => 'test');
$this->validate($request,$rules,$message);
//Handle File Upload
if($request->hasFile('image')){
//Get filename with the extension
$filenameWithExt = $request->file('image')->getClientOriginalName();
//Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
//Get just ext
$extension = $request->file('image')->getClientOriginalExtension();
//Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
//Upload Image to public folder
$path = $request->file('image')->move(public_path("/uploads"), $fileNameToStore);
}
else
{
$fileNameToStore = 'noimage.jpg';
}
// Create Post
$post = new Post;
$post->title = $request->input('title');
$post->body = $request->input('body');
$post->monday = $request->has('monday') ? 1 : 0;
$post->tuesday = $request->has('tuesday') ? 2 : 0;
$post->wednesday = $request->has('wednesday') ? 3 : 0;
$post->thursday = $request->has('thursday') ? 4 : 0;
$post->friday = $request->has('friday') ? 5 : 0;
$post->saturday = $request->has('saturday') ? 6 : 0;
$post->sunday = $request->has('sunday') ? 7 : 0;
$post->immer = $request->has('immer') ? true : false;
$post->timefrom = $request->input('timefrom');
$post->timeto = $request->input('timeto');
$post->ort =$request->input('ort');
$post->user_id = auth()->user()->id;
$post->image = $fileNameToStore;
$post->save();
return redirect('/posts')->with('success', 'Post Created');
}
Please or to participate in this conversation.