Laravel returning a 404 on an image - angularjs

This should be fairly simple though it is completely stumping me.
I have a backend Laravel installation running on localhost:8000
I have a front end Angular app running on localhost:9001.
I have some 'static' images I have included in my seed data (eg.
'1', 'user.png'), these images are being rendered perfectly in my front end (they are also served from the exact place my image uploads are going).
The URL I am currently serving images from is http://localhost:8000/images/{filename}
I can upload images from the front to the back end and they appear in the DB and the image is being put in the filesystem, I'm populating the correct URL in my front end (as evidenced by the previous URL).
My uploaded images are not being shown.
In my logs I am getting:
[2015-01-20 18:13:49] local.ERROR: NotFoundHttpException Route: http://localhost:8000/images/j249ae747ce28c317e02f1fb6d0a10c3.jpg [] []
[2015-01-20 18:13:49] local.ERROR: exception 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'
I tried a method in my routes file, but couldnt see why, when I am already serving some images already?
I have also set all permissions to 755 on my /images folder.
Any ideas?

I'm not sure I follow every bit of multi-system interaction you have going on, but I'd drop back to first HTTP principles.
Try accessing the image URL directly.
http://localhost:8000/images/j249ae747ce28c317e02f1fb6d0a10c3.jpg
If the error in your browser (or your logs, if you're not developing with debug set to true) is
local.ERROR: NotFoundHttpException Route: http://localhost:8000/images/j249ae747ce28c317e02f1fb6d0a10c3.jpg
This means your web server couldn't find a file at images/j249ae747ce28c317e02f1fb6d0a10c3.jpg, and handed the request to Laravel. This means you need to figure out why your webserver can't see the file.
Assuming you're serving index.php from the public folder
Do you have a public/images/j249ae747ce28c317e02f1fb6d0a10c3.jpg file?
Are you sure? Copy and paste the path into terminal and to a ls public/images/j249ae747ce28c317e02f1fb6d0a10c3.jpg to make sure your brain isn't missing some subtle case issue
Are any errors showing up in your web server's logs (not Laravel's)
Can you create a text/html file in the images folder and serve it? If not, then you may not be pointing your web server at the folder you think you are.
Something like
http://localhost:8000/images/test.txt
http://localhost:8000/images/test.html
Some first principles debugging like that should point you in the right direction.

rm public/storage
php artisan optimize:clear
php artisan storage:link
This worked for me.

The problem is you haven't generated a url for your uploaded image
Try accessing your url like this
http://localhost:8000/storage/images/j249ae747ce28c317e02f1fb6d0a10c3.jpg
To generate the above url
Add this method \Storage::disk('public')->url(); method in your controller.This method accesses the public disk array which is found in Config\filesystems.php and it generates a url in the following format
http://localhost:8000/storage/images/j249ae747ce28c317e02f1fb6d0a10c3.jpg
For example the method below stores the image in the image folder and generates the url of the image path.
public function uploadImage(Request $request)
{
$request->validate(['image'=>'file|image|max:5000']);
$imageProfile = new ImageProfile();
if($request->hasFile('image') && $request->file('image')->isValid())
{
$image = $request->file('image')->store('images');
$imageProfile->image_profile_url = \Storage::disk('public')->url($image);
$imageProfile->save()
}
return response()->json($imageProfile,200);
}
The code returns a Json response below
{
"id": 13,
"image_profile_url ": "http://127.0.0.1:8000/storage/images/cxlogqdI8aodERsmw74nmEx7BkxkWrnyJLMH7sFj.jpeg",
"updated_at": "2020-01-13 16:27:37",
"created_at": "2020-01-13 16:27:37",
}
Try to copy the url and test it in postman.
Visit the link to learn more about Laravel file storage
Laravel File Storage
Hope it helps.

laravel 8
Controler function
public function store(Request $request)
{
$this->validate($request, [
'site_title' => 'required',
'logo_image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$input['logo_image'] = time().'.'.$request->logo_image->getClientOriginalExtension();
$request->logo_image->move(public_path('images'), $input['logo_image']);
$input['site_title'] = $request->site_title;
//dd($input);
Site_settings::create($input);
return back()->with('success','Image Uploaded successfully.');
}
blade view
<td>
<img src="{{ url('/images/').'/'.$site_settings->logo_image ?? '' }}" alt="" width="250px" height="auto">
</td>

Related

Is there a way to rename automatically generated routes JSON file in Next.js?

I have a problem, when I click to go to the /analytics page on my site, adblockers block the analytics.json file that's being requested by Next.js as they think it's an analytics tracker (it's not, it's a page listing analytics products).
Is there a way to rename the route files Next.js uses when navigating to server-side rendered pages on the client-side?
I want to either obfuscate the names so they're not machine readable, or have a way to rename them all.
Any help appreciated.
With thanks to #gaston-flores I've managed to get something working.
In my instance /analytics is a dynamic page for a category, so I moved my pages/[category]/index.tsx file to pages/[category]/category.tsx and added the following rewrite:
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: "/:category",
destination: "/:category/category",
},
];
},
};
This now gets the category.json file rather than analytics.json, which passes the adblockers checks and renders as expected.
Note that due to having a dynamic file name in the pages/[category] directory (pages/[category]/[product].tsx), I had to move that to pages/[category]/product/[product].tsx as I was seeing the /analytics page redirected to /analytics/category for some reason without this tweak.

Error Image Upload and Get, Method App\Image::__toString() must not throw an exception, caught Illuminate\Database\Eloquent\JsonEncodingException

I am uploading user profile image which is uploading and moved to storage/app/upload/images folder but when I am trying to display that image, below given error occurs.
Method App\Image::__toString() must not throw an exception, caught Illuminate\Database\Eloquent\JsonEncodingException
Here is my controller function for displaying
public function userProfile() {
$image = Image::all();
return view('frontend.layouts.Profile',compact('image'));
}
My view in which I am displaying image
#foreach($image as $images)
<img style="width:210px ; height: 230px " src="/storage/app/upload/images/{{$images->image}}" >
#endforeach
Please Upload your image in Public directory and then try to access that, it will work fine
There are three ways of making an image available to a user:
1. As a public asset
Here the image is made available to everyone. For instance your website logo, or landing page image would be accessed by all. So there is a url to the image that is easily accessed by all. These sort of files would go straight to public/img/ folder.
2. As a protected image available only if specific url is requested
Here user specific images would be accessed by specific people. Think of your members' personal photos that you want to make available only to the member herself or to some specific person. In this case you would store the images in storage/app/public and make a symlink using the artisan command php artisan storage:link You can read more on this here. Assuming that you store your files using random names using str_random() you would then generate urls to your image using the asset() helper like: echo asset('storage/X3jf5j5b2j3n.jpg'); Given that the file names are random, it would be hard to access this image by everyone excepting those who have the url generated using the asset() helper.
3. As a protected image made available using Intervention library
In this case you would first check if user is logged in and then dynamically load the image using Intervention via another protected route. So in your web routes you would first have the user authorization using auth middleware:
Route::group(['middleware' => 'auth'], function () {
Route::get('user', 'UserController#userProfile');
Route::get('images/{image}', 'UserController#serveImage'); // this route serves the image only if user is logged in
});
Then once your have installed Intervention library using composer, our UserController would look like:
use Intervention;
class UserController extends Controller
{
public function userProfile()
{
$images = Image::all();
return view('frontend.layouts.Profile', compact('images'));
}
public function serveImage($image)
{
$filename = storage_path('app/images/'.$image);
return Intervention::make($filename)->response();
}
}
You can see that the image is now being served from the storage folder and not public folder. So this method serveImage() is called only when the route defined earlier for it is authorized. Intervention then works its magic to read the image and send it as a http response.
Your view would change one tad bit to accommodate the new route end point that we defined called images. I assume here that you are storing the filename of the image in db by a field named filename:
#foreach($images as $image)
<img style="width:210px ; height: 230px " src="{{ url('/images/'.$image->filename) }}" >
#endforeach
Note: Do bear in mind that the preferred way to serve images is by using method 2 since it is much faster. You can use method 3 sparingly if you really don't want anyone to even stumble upon the files using the urls.

Meteor FS link leads to 404 Error

I am currently developing a Meteor React app, which is using the ostrio:files package to store audio files in a collection named Files. In another (regular mongo) collection, I am using the following code in the transform function to "join" the document with the link to the audio file:
transform: function(doc){
let curAudio = doc.audio;
let audioFile = Files.collection.findOne({_id: curAudio.file_id});
if(audioFile){
curAudio.audioLink = Files.link(audioFile);
curAudio.audioLength = audioFile.meta.length;
curAudio.audioSize = audioFile.size;
doc.audio = curAudio;
}
return doc;
}
This seems to work just fine, as the resulting audio.audioLink is something like
http://localhost:3000/cdn/storage/files/8Q7WwEXyJSkNWwFQa/original/8Q7WwEXyJSkNWwFQa.m4a
But when I try to do something like this
<audio controls preload="none" style={{width: "480px"}}>
<source src={track.audioLink} type="audio/mp4"/>
<p>Your browser does not support HTML5 audio.</p>
</audio>
To be able to play the file, everything works until I click the play button of the HTML5 player. Then, chrome outputs to the console, that the server returned 404 when the file was supposed to be loaded. I tested putting the link into the adress bar, here the server response is just
File Not Found :(
Does anyone have an idea how to fix this?
I found the answer:
My local Ubuntu installation was apparently configured to store uploaded files in /tmp, which didn't caus problems until I restarted the system or cleared my temporary files otherwise. Having the server recreate the DB fixed the problem.

Laravel RESTful returning 301 state

Mates,
I'm developing a Backbone/Laravel application.
When I try to send a POST request to a certain resource, it returns me 301 status with no response, regardless that on the controller i'm printing a 'hello world', to check if it's getting to that point.
Here's some code...
public function store()
{
//
return 'hello world';
}
This is the routes.php
Route::group(array('before' => 'auth'), function()
{
Route::get('/', 'SitesController#index');
Route::resource('rooms', 'RoomsController');
});
So, when I make a POST request to
rooms
With some info to save, it gives me back 301 status with no response at all.
Any idea what am I doing wrong?
Thanks in advance!
Solved!
On backbone collection configuration, I had url parameter with '/' at the end.
rooms/
Deleted that slash and now it works fine.
Hope someone find's this helpful
(Adding this answer in case anyone has the same issue as me)
In my case I had a resource videos which gave the exact same problem. The reason was that I also had a directory on the server /videos/ (with files in it) which the server tried to point me to before it let Laravel direct it to the controller.
For some reason, posting to "image" in Laravel, even without a trailing "/" gives me a 301 Moved Permanently HTTP response.
I don't have an "image" folder in my public directory and still don't understand why the redirect occurs.
Changing the request to "foo" seems to work fine.
So if you found this page because you're trying to store an image restfully, try something like this:
Route::resource('api/image', 'ImageController');

Nginx config for serving snapshots to the Google bot

I have an AngularJS app which I'd like to get indexed properly on Google.
I wrote a client that scrapes the sites for links and then downloads the pages with Phantomjs making snapshots. This all works fine. What I'm having a problem with is serving those snapshots to the Google bot.
For some reason, the Google bot appends ?_escaped_fragment= to my URLs. As an example, http://me.com/about gets changed to http://me.com/about?_escaped_fragment=. I've verified this in the access logs.
I'm trying to catch this request and serve the Google bot the snapshot with this config:
location / {
if ($args ~ "_escaped_fragment_=") {
rewrite ^ /snapshots/$1;
}
}
However, requesting this URL: http://me.com/about?_escaped_fragment= always results in a 404. Same with the other pages.
The snapshots are stored in /snapshots, relative to the root of the website. They're named after their pages, following directory structure, so http://me.com/business/register has a snapshot in /snapshots/business/register.html.
What can I do to get these snapshots to work?
Thanks.
Ok first let me explain why google uses ?_escaped_fragment_, This is used for websites that rely on ajax, and mark their page with hashes, like for example if you have http://example.com/gallery/#!image1 and each time the user changes to the next image you update the hash to image2, image3, but if the user goes directly to http://example.com/gallery/#!image50 your javascript uses that hash to load the 50th image directly instead of image1 ( servers can't see the hash part, only javascript can ).
So google uses this _excaped_fragment_ to tell the server which page it's trying to cache.
For more explanation use this link
As for why you get a 404 error, I think because you used a $1 without using a capturing block, The right rule would be something like this
location / {
if ($args ~ "_escaped_fragment_=(.*)") {
rewrite ^ /snapshots/$1;
}
}
But I don't think this will fix your problem, because according to your example, you didn't use hashes, you used the uri of the page, so i would rewrite the rule to something like this
location / {
# try snapshot, if not found try direct file.
try_files snapshots$request_uri.html $uri;
}
Here is what I have in nginx and it is working fine, you might need to add a special one for index.html (i.e. when accessing the root of your website)
if ($args ~ "_escaped_fragment_=/(.+)/?") {
set $path $1;
rewrite ^ /snapshots/$path.html;
break;
}
location /snapshots/ {
internal;
alias /var/www/snapshots/;
}
So http://me.com/?_escaped_fragment_=/about will access /var/www/snaphots/about.html
Don't forget this meta tag as well in your page if you use html pushstate instead of hashbangs:
meta(name="fragment", content="!")

Resources