I am developing a MEAN stack application and i want to display the images with some responses.
Exact Requirement: There is search box , when user enter the name of the image , server should respond with that image and browser display that image.
I have maximum of 70 images with size 30kb maximum.
Should I store these inside the mongoDB and for every request node server hit the mongodb and serve that image in the response or I serve it with Angular.js?
Please recommend the efficient way to do that.
You can setup a folder for static content (CSS, images, etc) do it in your expess.js configuration probably you'll find something like this:
app.use(express.static(path.resolve('./public')));
app.use('/images',express.static(path.resolve('youPathToStaticimages')));
Then create a collection with the image metadata, like file name, size, uploaded date, friendly name and maybe tags or any other field that you can query.
Then use an endpoint / $resource combination and retrieve the data and display the images in the client with a simple HTML image tag (IMG) and use ng-src, probably within a ngRepeat.
For me that could be the easiest way to do it, also you can set some sort of cache policy to your image folder in apache or ngnix.
You've got a little over 2mb of data which can be easily cached. Transferring from the database to the web server or retrieving from disk is extra work. Load all the images into your node thread and when the keyword comes through send the cached image.
Related
I watched a tutorial where they showed that appending ?${new Date().getTime()}to the value of src attribute in the image tag, updates the current image with the new image.
I came across this question, where the first answer to the question has followed the same technique.
Could someone please explain to me the rationale behind the working of this particular technique. Thanks!
Simplest explanation is that the browser (and often the server) will cache items in memory to decrease page load times. Therefore, if you have a dozen pages that all are referencing /images/logo.png, the image is downloaded once and stored so that it can be re-used on each page. Efficient, right?
Anyways, sometimes images change and you don't want that to happen, so what you do is change the name of the file. For example, /images/logo.png?15, /images/logo.png?16, /images/logo.png?17, etc. The browser no longer attempts to use the cached image because the query is actually different.
The code snippet you've included simply includes the current time to the name of the file in order to make it unique.
Different query parameters can result in a server serving different images, depending on the backend logic. This is often not the case - in many setups, requesting the same path with different query parameters will give you the same image in return, but that's not always the case.
If a browser sees an image URL whose image exists in the cache already, it will not download the image again - instead, it'll take the image from the browser cache. But if you change the src to one which is not in the cache, it will make another request to the server. If the server has changed the image at that endpoint between initial pageload and src change, the new image on the server will be downloaded and displayed on the client.
The new Date().getTime() is just a way to append a string which definitely does not exist in the browser cache yet.
So I have a question concerning security. Imagine that I have uploaded a picture of an animal to the server. I have saved 1545419953137bear.jpg on the backend in my uploads folder where I save all my images.
On the frontend I have this img element where I use [src] to dynamically create a path to this uploads folder to retrieve this image of a bear.
My question is now: Is this the correct way to do this or does this leave me vulnerable to security issues? And if so, what would be a better way to handle this?
on the left side you see the uploads folder of the backend, right side how I create this file
html code (angular)
<img [src]="linkImg(post.fileName)">
component method: this method returns a url that will display the image. Is this the right way to do this or is this lacking security?
linkImg(fileName) {
// base_URL returns localhost:3000 or the production URL
return `${this.BASE_URL}/uploads/${posterProfilePic}`;
}
Its a good way to handle the serve images. Keep in mind your server should be secure.
In case you want to protect the images for public display you need to make them secure through a middleware or any of the server technique and checking is an authenticated request or not.
From angular side it is good.
A read for security
https://nodesource.com/blog/nine-security-tips-to-keep-express-from-getting-pwned/
Basically, this app should contain a collection of objects in a view showing a representative image of each object (i.e. a movie should show its poster).
Talking about movies, I am trying to use the IMDB APIs in order to retrieve the metadata for a certain movie title, including its poster. However, hotlinking won't let me display the images once their URLs are obtained from the APIs (I keep getting the "GET [...] 403 Forbidden" error...).
Since I am using the JSONStore feature in order to cache the data, I would like to know if there is a possibility to store those images in JSONStore and then display them like a normal browser would do. I am trying to do all this sort of things from the front-end side, not the back-end one, using AngularJS, HTML5 and JavaScript.
Do you have any suggestions for this kind of problems?
Thank you.
Suggested solution: What you'd need to do is to encode the images to base64 and this way you could store the binary image as a string inside your JSONStore collection.
When you then need to display it you will need to base64 decode the string back into an image and display it in your HTML
So i have a canvas on which the user signs, now instead of converting it to a base 64 string i simply want to save it as an image itslef. whats the easiest way to do it html5??
You can easily do that this way (specifying the format as png in this case):
var img = canvas.toDataURL("image/png");
You can specify different image formats.
Take a look at this answer.
I've answered a similar question here:
Simulating user event
Assuming you are saving locally
You can go the route of creating an image from a Data URL, but then saving it is the trickier part that currently isn't very nice using HTML5. It's hopefully going to get better soon, if browsers incorporate the download attribute of the a tag.
Obviously if you have higher permissions than a standard webpage... i.e. you are designing a browser plugin - then there are other options...
If I were to implement something like this myself, at the moment, I would conceed to using a flash plugin to handle the save to the local computer.
Assuming you are saving remotely
By the sounds of it you aren't saving to a server, but if so this is quite easy by just POSTing the base64 information to a script written in a server-side scripting language (i.e. like PHP) and getting that to write the data directly as binary to a file. Obviously you have to make certain you do this securely however, you don't want just any binary data written to your server's filesystem.
Best of both worlds
If you've got the development time, the best method to get a canvas image saved locally - without Flash - is to create a server-side script that instead of saving the data to your server actually writes the Base64 information you send it directly back as a realised binary image file. That way you can create a form that posts your Base64 data to a new tab, this request is evaluated by the server-side, and the binary image is returned... at which point the browser asks the user where they wish to save their image.
You'll need to define the correct headers to force an image to download (rather than display in-browser). A simple change to force this is to set the server-side script's Content-type header to 'image/octect-stream'... there are other header options to set which would be best researched (i.e. headers that control the filename and so forth).
reflect.php
<?php
/// a simple example..
if ( array_key_exists('data', $_POST) && ($data = $_POST['data']) ) {
header('Content-type: image/octet-stream');
echo base64_decode( $data );
exit;
}
and the form...
<form action="reflect.php" method="post" target="_blank">
<input name="data" type="hidden" value=" ... Base64 put here with JS ... ">
</form>
(The whole form should be created dynamically and submitted automatically with JavaScript)
Improving the user experience
There are ways to avoid a new tab being created, but you'd have to research to make sure these other methods don't cause cross-browser problems... for example you could post your form data as part of an iframe (which would keep the process hidden), or just post the data directly on the current window (..and hope that all the browsers receive the correct request and open a download rather than replace your page content - most modern browsers should handle this).
Improving security
With regards to a PHP script that automatically returns binary data, you should keep the access to this script secured by one time use key / authentication token or something similar, and keep a limit on how much Base64 data you are willing to accept. It might not seem like it poses a secutiry risk - as you are not modifying your server in any way with what the user sends - but the dodgy people of this world could take your script and use it to send download request to other users... which if downloaded (and turned out to be unwanted trojans or viruses) would make your server implicit in providing the dodgy file.
All in all
Due to the effort required to get a simple thing like an image saved to the desktop, I wouldn't blame you for doing the following:
Embed the image in the page (after taking your snapshot from canvas) and ask the user to right click and Save as...
Hopefully future things will make this situation better...
Is there any way (server or client side) to force the browser to pull a new version of a file (image) from the server. The image in question is otherwise cached for a long time. I know I can append a random number, for instance, to the URL of the image but this is not acceptable in this situation. I need for the image to be refresh from the exact same URL.
What I'm doing: a YouTube like portal where users upload videos. Each video has a thumbnail which is shown on various pages on the portal. User can, at any time, change the thumbnail (he can select from three generated thumbnails). So when this happens (a new image overwrites the 'original' image), I wan't to refresh the video's thumbnail so that the owner (I don't care if other users see the old thumbnail) will see the new thumbnail no matter where the thumbnail is shown.
I'm afraid this can't be done but I'm asking here just to be sure.
update: I'm using nginx and PHP on the server side
You could use ETAGs on your thumbnails. This would prevent the transmission of the actual thumbnail data if it hasn't changed (i.e. still has the same hash). However, you would still face the clients HTTP requests to check if the ETAG has changed (normly to be answered by HTTP 304.
But combined with a rather short freshness threshold (say a couple of minutes), you could achieve tradeoff between caching and freshness while still conserving resources. If you need absolute freshness, you might have to stick to ETAGs though. If you create a clever hash function, you could handle the ETAG requests on your frontend loadbalancer (or at least near it) which could thus be rather cheap.
Edit: Add alternative from my other comment.
An alternative could be to use added request parameters to force a re-fetch when the resource changed as suggested in another answer. A variation of that schema (which is used by many Rails applications) is to append the timestamp of the last change (or some kind of hash) as a parameter to the file which only changes when the file actually does change. Something like this, or one of the above methods, is actually the only way to be really sure to not have unnecessary cache validation requests while at the same time having always the freshest resource.
Add at the end of the filename a get parameter, such as:
example.jpg?refresh=yesplease
You could also refresh that image each visit by using a rand() param.
In php:
example.jpg?refresh=<?php echo rand(1,999); ?>