retrieving an image from the file path in the database in cakephp - cakephp

I am using the following code
echo $this->Html->image($article['Article']['image']);
to retrieve an image from a path in the database, but instead the browser retrieves the following
<img src="/loopmatic/img/uploads%5CIMG_0567.JPG" alt="">
Can someone help in explaining an alternative method to use, or why i see a percentage sign in the path instead of a forward slash

%5C is the '\' character urlencoded. URL's are not like file systems so you have to turn the \ in a /.
I've written a complete file storage and image processing system that deals with that as well. Check it out here or just grab the method from the helper.
public function normalizePath($path) {
return str_replace('\\', '/', $path);
}

Related

CakePHP - Router::url() generating url relative to current page

I'm trying to replace all of my static routes with the CakePHP 3.8 Router::url() method.
On my local environment, when accessing the the below code from the manage/lender-products/read/2 route, I get the expected results of /manage/lenders from the below code:
\Cake\Routing\Router::url(['controller' => 'Lenders', 'action' => 'index'])
However, on production (bref.sh/AWS Lambda/PHP 7.4), I get the unexpected result of /manage/lender-products/read/manage/lenders.
It appears that in my production environment, the URL is being generated and is including the current pages url in the end result.
In case you do not set a custom base path for the App.base config option, CakePHP will try to figure the possible base path out on its own, based on $_SERVER['PHP_SELF'] and $_SERVER['DOCUMENT_ROOT'], so it's likely that one or both of these contain unexpected values in your AWS environment.
The simple fix would be to manually set the base path in your config/app.php. If your application doesn't actually live in a public subdirectory (ie in case webroot is your document root), then you should set the path to an empty string, otherwise provide the path, like /my/app (with a leading slash, but without a trailing slash!).
See also
Cookbook > Configuration > General Configuration

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.

Laravel returning a 404 on an image

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>

CakePHP generate a Document to Webroot

I'm currently working with cakephp and I am generating a word document. My problem is how can I put the generated document on my web root and not as a download.
I am guessing you are using an action to generate a document, which gets output to the browser.
You should either use output buffering to "catch" the output and then write it to a file, or write the document data to a string, and write that string to a file on the server.
EDIT:
PHPWord has a SAVE method. In your action, you can save the document to a certain location, but output something else, i.e. success notification. This way, your action only generates the file:
public function generateWordDocument(){
//... your word file creation...
$wordDocumentLocation = TMP . 'word_files/';
$objWriter = PHPWord_IOFactory::createWriter($PHPWord, 'Word2007');
$objWriter->save($wordDocumentLocation . 'helloWorld.docx');
$this->Session->setFlash('Document generated!');
$this->redirect(array('action'=>'index')); //or wherever you want
}
If you want to protect that file, you could save the file to a "secure" folder (this can either be a folder outside the "app/webroot" folder, or a folder protected with .htaccess deny all instruction) and than use another action, like "getWordDocument":
function getWordDocument($documentName){
$wordDocumentLocation = TMP . 'word_files/';
if (file_exists($wordDocumentLocation . $documentName)) { //this is not really the safest way of doing it
$fp = fopen($wordDocumentLocation . $documentName, 'rb');
header("Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");
header("Content-Length: " . filesize($wordDocumentLocation . $documentName));
fpassthru($fp);
exit();
}
}
Please note, that this code is just for "grasping the concept" and is in no way safe or optimal.
i think you want to add file in webroot but it is not downloadable for public users ,
You have several ways :
- protect folders with .htaccess (Like Js folder)
- create new folder in app folder like webroot and put files in it
- use Dispatcher Filters in cakephp : http://book.cakephp.org/2.0/en/development/dispatch-filters.html
and ....

Codeigniter "file_exists($filename)"

Need help with the codeigniter, I think file_exists is for server path, not for url. but my image folder got same level with application and system folder. find nothing on google, please help
$url=base_url();
$filename="$url/upload/$id.jpg";
if (file_exists($filename)){
echo "<li><img src=\"".$url."upload/$id.jpg\" width=\"40\" height=\"40\" /></li>";
}else{
echo "<li><img src=\"http://www.mydomain.com/haha/image/noimg.png\" width=\"40\" height=\"40\" /></li>";
}
Codeigniter is always running on index.php, so all paths are relative from there. You can use any of the following, assuming upload/ is at the same level as index.php:
file_exists("upload/$id.jpg")
file_exists("./upload/$id.jpg")
file_exists(FCPATH."upload/$id.jpg")
FCPATH is a constant that Codeigniter sets which contains the absolute path to your index.php.
As a side note, I prefer is_file() when checking files, as file_exists() returns true on directories. In addition, you might want to see if getimagesize() returns FALSE to make sure you have an image.

Resources