I have a networked camera that generates a video snapshot upon hitting http://192.0.0.8/image/jpeg.cgi. The problem is that by accessing the root (i.e. 192.0.0.8) directly, users can access a live video feed, so I hope to hide the address altogether.
My proposed solution is to use PHP to retrieve the image and display it at http://intranet/monitor/view.php. Although users could create motion by hitting this new address repeatedly, I see that as unlikely.
I have tried using include() and readfile() in various ways, but do not really use PHP often enough to understand if I'm going in the right direction. My best attempt to date resulted in outputting the jpeg contents, but I did not save the code long enough to share with you.
Any advice would be appreciated.
If you want to limit requests per user then use this:
$timelimit = 30;//Limit in seconds
if(!isset($_SESSION['last_request_time'])) {
$_SESSION['last_request_time'] = time();
}
if(time() > $_SESSION['last_request_time'] + $timelimit) {
//prepare and serve a new image
} else {
//serve an old image
}
If you want to limit image refresh time then use the same script but save the last_request_time in place shared for all users(DB, file, cache)
A succinct way to do this is as follows:
header('Content-Type: image/jpeg');
readfile('http://192.0.0.8/image/jpeg.cgi');
The content of the jpeg is then streamed back to the browser as a file, directly from http://intranet/monitor/view.php.
Related
I have a website with images upload/show functionality on it. All images are saved into filesystem on a specific path.
I use Yii2 framework in the project. There isn't straight way to the images and all of them requested by specific URL. ImageController proceses the URL and takes decision about image resizing. ImageModel does the job. The user get image content.
Here the code snippet:
$file = ... // full path to image
...
$ext = pathinfo($file)['extension'];
if (file_exists($file)) {
// return original
return Imagine::getImagine()
->open($file)
->show($ext, []);
}
preg_match("/(.*)_(\d+)x(\d+)\.{$ext}/", $file, $matches);
if (is_array($matches) && count($matches)) {
if (!file_exists("{$matches[1]}.{$ext}")) {
throw new NotFoundHttpException("Image doen't exist!");
}
$options = array(
'resolution-units' => ImageInterface::RESOLUTION_PIXELSPERINCH,
'resolution-x' => $matches[2],
'resolution-y' => $matches[3],
'jpeg_quality' => 100,
);
return Imagine::resize("{$matches[1]}.{$ext}", $matches[2], $matches[3])
->show($ext, $options);
} else {
throw new NotFoundHttpException('Wrong URL params!');
}
We don't discuss data caching in this topic.
So, I wonder about efficient of this approach. Is it ok to return all images by PHP even they aren't changed at all? Will it increase the server load?
Or, maybe, I should save images to another public directory and redirect browser to it? How long does it take to so many redirects on a single page (there are can be plenty images). What about SEO?
I need an advice. What is the best practice to solve such tasks?
You should consider using sendFile() or xSendFile() for sending files - it should be much faster than loading image using Imagine and displaying it by show(). But for that you need to have a final image saved on disk, so we're back to:
We don't discuss data caching in this topic.
Well, this is actually the first thing that you should care about. Sending image by PHP will be significantly less efficient (but still pretty fast, although this may depend on your server configuration) than doing that by webserver. Involving framework into this will be much slower (bootstrapping framework takes time). But this is all irrelevant if you will resize the image on every request - this will be the main bottleneck here.
As long as you're not having some requirement which will make it impossible (like you need to check if the user has rights to see this image before displaying it) I would recommend saving images to public directory and link to them directly (without any redirection). It will save you much pain with handling stuff that webserver already do for static files (handling cache headers, 304 responses etc) and it will be the most efficient solution.
If this is not possible, create a simple PHP file which will only send file to the user without bootstrapping the whole framework.
If you really need the whole framework, use sendFile() or xSendFile() for sending file.
The most important things are:
Do not use Imagine to other things than generating an image thumbnail (which should be generated only once and cached).
Do not link to PHP page which will always only redirect to real image served by webserver. It will not reduce server load comparing to serving image by PHP (you already paid the price of handling request by PHP) and your website will work slower for clients (which may affect SEO) due to additional request required to get actual image.
If you need to serve image by PHP, make sure that you set cache headers and it works well with browser cache - you don't want to download the same images on every website refresh.
I have a question. I would like to add rotating links inside my email signature to
track results on my site. I can make these dynamic tracking urls on google as you may know
but I would like to rotate them inside my email signature to see which text draws the most
conversions or returning visitors.
Is this possible?
I found this for instance:
$mybanners[1] = '<img src="banner1.jpg">';
$mybanners[2] = '<img src="banner1.jpg">';
$id = rand(1,2);
echo $mybanners[$id];
But when I look into my windows live mail I can only upload html files.
Does someone know how to do this?
You can't provide PHP scripts in a mail, since it is a server-side language and it will be opened by a mail client. Even Javascript is very often blocked for security reason.
What you can do is make a "fake" image which will be in fact generate by a PHP script. YOu can find inspiration by looking to script made for forum avatar rotation. The idea is to generate an image, which will be displayed to the client but, in the same time, save some data about the user who requests the image if you want:
<?php
// Save whatever you want about the user
file_put_content("log/user.txt", $_SERVER['HTTP_REFERER']);
// Render a valid PNG image
header('Content-Type: image/png');
readfile("/path/to/banner.png");
?>
This script should be used as a standard image (with, if you want, a nice URL rewrite to make a .png link):
<img src="http://www.example.com/my_super_banner.php" />
where my_super_banner.php is the script described before.
I'm making a data visualisation tool that works using SVG, d3.js and JQuery. I am currently making a feature to export (and download) as an SVG file:
// Code on main page
var svg = $("#svg-wrap").html();
var win = window.open("export.php?svg=" + svg, '_blank'); // _blank means export.php opens in a new tab
win.focus;
// Code in export.php
<?php
ob_start();
header("Content-Type: application/octet-stream");
header("Content-disposition: attachment; filename=data.svg");
$svg = $_GET["svg"];
echo stripslashes($svg);
?>
This doesn't work though, because although some of the SVG is passed through, the full code is too long for a query string (or so it seems).
Is there some way that I can fix this? I could use compression, but that would only shrink it up to a limit and I think it would probably still be too long - the SVG code could be hundreds of lines :( .
Most UAs put limits on GET requests. Use POST instead.
You can store it in session variable and access it on other page... but not the best practice though...
You may want to use window.postMessage to handle the communication between your main app window and your popup, this way you could just stay on the client side only.
It is hard to tell the limitation,
a browser can have a limit, for post vs get
a proxy can have a limit, for post vs get
a web server can have a limit, for post vs get
the application itself can set a limit...
etc
As suggested, you could go with writing a svg file and send the url instead.
How big is the svg file?
Last week I converted my page img src values from pointing at image files to using a PHP script to serve up the images. The primary reason was to accommodate both files and database BLOBs as the actual source.
Now when a user goes to a page, sometimes images show and sometimes not. If not, and the page is refreshed\reloaded, then the image appears. When images do not appear, sometimes it is an image the user has already accessed previously today.
I am stumped.
Here is the img tag:
<img src="../somedir/image_script.php?i=1234">
The image_script.php file figures out where to get the image from, then finishes up with:
header("Content-type: image/jpeg");
if($from_db){
print $image_blob;
} else {
$im = imagecreatefromjpeg($image_file);
imagejpeg($im,null,100);
imagedestroy($im)
}
I am using PHP 5.2.8 on IIS 6 using FastCGI. There are no cache headers on the image_script.php file nor on the directory it is in. Currently 99.9% of the images are file based, so I do not know if there is a difference in result between db-based and file-based images. When I go directly to image_script.php in my browser it returns the requested image (i=????) 100% of the time.
a> Any clue as to why the hit and miss with images being displayed? and,
b> what would be a proper way to actually cache the images served up by the PHP script? (they are very static)
Scott
Hmm. Can't tell for sure, but maybe your imagecreatefromjpeg is occasionally running out of memory? In that case, you'd serve an error message out as JPEG data and never see it, right?
Incidentally, wouldn't just grabbing the image file in as a string and shovelling it out without going through imagecreatefromjpeg/imagejpeg/imagedestroy be more efficient? It looks like you're reading a JPEG file, creating an internal PHP memory image from it, then reconverting it to a JPEG (at hefty 100% quality) then serving that data out, when you could simply read the JPEG file data in and print it, like you do from the database.
What happens if you do, say...
...
} else {
header ('Content-length: ' .filesize($image_file));
readfile ($image_file);
}
I would like to generate a dynamic image from a script, and then have it load to the browser without being persistent on the server.
However, I cannot call this by setting the image's src="script.php", since that would require running the script that just generated the page and its data all over again, just to get the final data that will generate the graph.
Is there a way to do this that is similar to setting image's src="script.php", but which is called from within another script, and just sends the image without saving it? I need access to the data that is used in the generation of the markup, in order to create this dynamic image.
Or, if not, what is the easiest way to destroy the image once the page is loaded? a quick ajax call?
Is there any way to cache certain data for some limited time frame in order for it to be available to some other script?
Any ideas would be greatly appreciated, as I'm having a really hard time finding the right solution to this...
Thanks!
You can inline the image into a <img> tag if you need to.
Like
<?php
$final_image_data; // Your image data, generated by GD
$base64_data = base64_encode($final_image_data);
echo "<img src=\"data:image/png;base64,{$base64_data}\" ... />";
?>
That should work on all modern browsers, and IE8. Doesn't work well with some email clients tho (Outlook, for one).
Also, another solution I found is to store the image in a session variable which is then called from a php script in the image tag. This would allow a user specific image to be served, and then removed from memory by the script... This also avoids messy img src="" tags...
Hopefully that is helpful to someone.
Use a rewrite rule.
RewriteRule ^magicimage.jpg$ /myscript.php
Then simply echo your image data from gd, instead of writing it to disk -- which is as simple as not providing a filename to the appropriate image*() function
myscript.php
<?php
$im = imagecreatetruecolor($w, $h);
//...do gd stuff...
header('Content-type: image/jpeg');
//this outputs the content directly to the browser
//without creating a temporary file or anything
imagejpeg($im);
And finally, utilize the above
display.php
<img src="magicimage.jpg">