So I have created a small app using node.js and have served my assets folder like so
app.use(express.static('assets'));
Now in my .ejs file I can reference an image easily, e.g.
var img = document.createElement('img');
img.src = '/img/picture.jpg'
Now, what I want to do is loop through all the images in that folder and display them on the page.
Something like
var images = new Array();
images = { All pictures in the /img directory }
images.forEach(function(image) {
var img = document.createElement('img');
img.src = image;
}
So my question is, how do I get the names of all the static images using JS? Do I instead have to make an AJAX call to the directory to read the file names? Or do this server-side with node.js and pass the images through to the .ejs file. Typically, which is better practice (can be a separate question but I thought I would ask)?
Thanks in advance
So my question is, how do I get the names of all the static images using JS?
The client knows nothing about what URLs the server will respond to until it makes a request to them.
Do I instead have to make an AJAX call to the directory to read the file names?
That would be one possible approach.
Or do this server-side with node.js and pass the images through to the .ejs file.
That would also work
Typically, which is better practice (can be a separate question but I thought I would ask)?
It depends.
Using Ajax would require a second HTTP request, but the response could be cached.
Doing it when the page loads would reduce the number of requests but on, but the work to get the list would have to be done every time the page loads and would increase the size of that page.
So which is best, using the only measurable metrics, depends on how often an individual is going to reload the page and how often the list changes.
Related
I'm trying to load a bunch of png images that are in a folder in my project. I'm using a function that takes in an array of strings that signify the name of the actual images.
The actual html that comes up in the console seems correct, however the images don't get loaded. The weird thing is, if I hard code in the html with the src of one of the images, the src in the inspector comes up as 'name.93439.png' with random numbers in between the name and the file extension, and the image shows up. But the source I am injecting in the javascript using template strings is no different than what I am putting into the html when I hard code it.
So is there something I'm missing here with loading images? Why does hard coding it in work, but when I try using JS it doesn't give the same results? Code below:
FILE STRUCTURE:
index.html
/src
index.js
/assets
/images
...{all of the images}.png
function loadImages(names) {
names.forEach((name) => {
let image = document.createElement('img');
image.src = `src/assets/images/${name}.png`;
let newDiv = document.createElement('div');
newDiv.appendChild(image);
document.getElementById('images').appendChild(newDiv);
});
}
This happens because parcel hashes your assets during building. When executing the js, ${name} is not aware of the (parcel) hash and therefore doesn't finds the correct file. Try to take out the assets from the build process and copy them to your dist folder (you'll probably want to automate this at some point). So the assets file names do not get hashed.
Im building a blog application and i just realized i can not use local file paths in react, and since the response of my REST api is a unique path for every image, i cant use it in react.
Is there a way of going around this without importing every single image?
This is what i am currently doing:
const imgSrc = this.state.post.img_path
const styles = {
background: 'url('+imgSrc+')'
}
and then i apply the styles to the element.
I do this cause soon im going to update it and make it so i will upload 3 different images for different screen sizes.
Solution:
Instead of storing my images outside of the public folder, i changed the upload location to store the images in the public/images folder. Thankfully i only had a few images so it wasnt that bad.
Then i set the url to be:
"https://localhost:3007/images/" + image name gotten from REST api response
and now it works.
Is it possible to add a file into the website's directory?
In other words, let's say I have a directory – as an example I'll call it "myWeb"– it has index.html and main.js.
In main.js, I want to add a new page to myWeb when I click a button, let's say secondindex.html (for now, I won't worry about overwriting the file when clicked again).
Is this possible? If not, are there other techniques, or is this too broad?
For security reasons, the client-side cannot directly write to the server-side as they're not connected with one another. If writing a file to the server is what you want, you'll need a backend server and some kind of API/script that you interact with and create files that way.
There are other ways that don't involved creating files, such as using a database or cloud solution like Firebase. However, there are perfectly valid reasons you might want to keep your site basic and write static files (speed being one of them) and not wanting to setup and maintain a database being another.
This can be done using the fs module in Node.js for example:
var fs = require('fs');
function generateHtml (req) {
return '<!DOCTYPE html><html><header><title>My Page</title></header><body><p>A test page</p></body></html>';
}
var filename = '/path/to/secondindex.html';
var stream = fs.createWriteStream(filename);
stream.once('open', function(fd) {
var html = generateHtml();
stream.write(html);
stream.end();
});
The above would be in a Javascript file server-side and then you would have some kind of server checking for a request (preferably this would be protected using a token or something) and creating the needed file.
The fs module in particular is flexible in that you can create files many different ways. The above uses streams and is great for when you're dealing with potentially massive files.
I have an pinterest like application. Images and other related information are stored in MongoDb. Generally size of images is about 1 mb. Images are displaying with infinite scroll. When long script with base64 string is loaded, browser crashes or response time is really high (especially for Internet Explorer)
What is the best way to display images that are stored in MongoDb?
I think the best way to achieve this, is to have you file physically in some public folder on your server. This should be accesible in a way that you will only need to use something like
http://www.myhost.com/images/my/path/to/image.jpg
You can still maintain your Base64 image in mongodb as backup, however, this is not the best way to retrieve you images due performance issues (as you have seen). I recommend you to do the following:
Each time you store the image on mongo, be sure to also store the "image file" as itself on some public place on your server. Have in mind that you should keep the path to that file on the mongo model you are using. So, the next time you call the object, rather than get the base 64 image, you should only get the path to the image.
Lets say, you have this model
myModel = {
name: "some name",
image64: "someextralongstringveryveryveryweird......",
imageUrl: "/images/my/path/to/image/imagename-id.jpg"
}
the next time you query on it, you can just ignore the image64 using mongo projection, and in you client side you just use some html tag that makes use of that url.
<img src="/images/my/path/to/image/imagename-id.jpg">
This will help you lots on performance.
There are some libraries that could help you to manage the image file creation. ImageMagick is one that I have used and is so versatile.
I guess you have some server side part of this application? Why don't you create a tiny API to retrieve images?
So your browser will have information about image and can ask your server for it, something in line of http://your_server/api/image/imageID or http://your_server/images/imagename and then your server would just stream this image, you don't need to store this in the file system.
On the client side (browser) you just need to implement 'lazy loading'.
If you're using MongoDB, you should be storing images in your database using GridFS (http://excellencenodejsblog.com/gridfs-using-mongoose-nodejs/), a feature which exposes something like a virtual filesystem for your application.
Using GridFS, you could write a controller method which streams a requested file from your MongoDB instance and pipes the file content to the response.
I would recommend storing the images on the filesystem and using your web server to handle serving them to clients.
For performance, I would put them on a CDN - that will be able to handle the traffic.
In your application storage (mongo), you can store a URL/location to the image and then use that when retrieving the image in your javascript code.
In addition, in your code I would recommend preloading images via javascript that preloads images before the user has scrolled to see them. There are some great tools out there that you can leverage for that.
In the off chance that you cannot change the storage and you have to use mongo the way it is - I would look at preloading images with javascript.
I was having the same issue. So i used a mongodb to store my images.
This is how I proceeded:
Define a logo schema:
var logoSchema = new mongoose.Schema({
name: String,
url: String
});
Compile the logo schema into a model:
var Logo = mongoose.model("Logo", logoSchema)
Creating a new logo:
var rectblack = new Logo({
name:"rect&black",
url:"public/image.jpg"
});
Saving it :
rectblack.save(function(err, logo){
if(err){
console.log("some went wrong")
} else {
console.log("logo saved")
console.log("logo")
}
});
Now to use this logo or image I just called it with the image tag (just the file name!!!):
<img src="/image.jpg">.
I have the following problem which I'm trying to solve with javascript. I have a div with a background image specified in a css file, and I want my javascript to change that image periodically (let`s say every 5 secs).
I know how to do that, the problem is that I have a folder of images to choose from for the back image. I need to be able to read the filenames (from the image folder) into an array, change the background image of the div, delay for 5 seconds and change again.
in your javascript, use an array like
var images = [ "image1.jpg", "image2.jpg", "image3.jpg" ];
function changeImage() {
var image = document.getElementById("yourimage");
image.src=$images[changeImage.imageNumber];
changeImage.imageNumber = ++changeImage.imageNumber % images.length;
}
changeImage.imageNumber=0;
setInterval(changeImage,5000);
The values in the array should be generated by your php
You're still going to need php or asp to query the folder for files. Javascript will not be able to "remotely" inspect the file system.
You can do something like the following in jQuery:
$.ajax({
url: 'getFolderAsArrayOfNames.php',
dataType: 'json',
success: function(data) {
for(var i=0;i<data.length;i++) {
// do what you need to do
}
});
});
And in your getFolderAsArrayOfNames.php, something like this:
echo "function "
.$_GET['callback']
."() {return "
.json_encode(scandir('somepath/*.jpg'))
."}";
If you are using Apache as your
web server, and
if you can configure
it to provide a default directory
listing for your images folder (use
the appropriate options in
httpd.conf and/or .htaccess), and
if you don't care that the list of
images is available to everyone who
visits your web site,
then you don't need PHP or any other server-side processing.
You can use XMLHttpRequest (or the jQuery ajax function, which is a nice wrapper) to get the listing for the folder. The response will be HTML and it will look something like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Index of /demo1/images</title>
</head>
<body>
<h1>Index of /demo1/images</h1>
<pre><img src="/icons/blank.gif" alt="Icon "> Name Last modified Size Description<hr><img src="/icons/back.gif" alt="[DIR]"> Parent Directory -
<img src="/icons/image2.gif" alt="[IMG]"> tree.gif 17-Mar-2009 12:58 6.2K
<img src="/icons/image2.gif" alt="[IMG]"> house.gif 17-Mar-2009 12:58 6.5K
<img src="/icons/image2.gif" alt="[IMG]"> car.gif 02-Mar-2009 15:37 8.4K
<img src="/icons/image2.gif" alt="[IMG]"> elephant.jpg 02-Mar-2009 15:37 3.4K
<hr></pre>
<address>Apache/2.0.63 (Unix) Server at zeppo Port 80</address>
</body></html>
Since this output is pretty predictable, you might try parsing out the filenames using a JavaScript regular expression, but it's probably just as easy and more robust to create a hidden DIV on your page, put the HTML response into that DIV, and then use DOM methods to find <a href>s that are after <img> tags with an alt="[IMG]" attribute. Once again, using jQuery Selectors or similar helper methods available in other toolkits will make this DOM parsing pretty easy.
Once you have the URL of the new image (parsed from the href), you can set the new CSS background for your div with the .style.backgroundImage property.
You cannot do any file IO using JavaScript mainly because of security reason, so anyway you have to create some back end service which will update you with an list of available files in your folder. You don't have to do it in a hard way, you can use AJAX to it smoothly and nicely
You can't read a folder's contents, neither on the server nor on the clientside.
What you can do is to read the folder's contents with the help of a serverside script, and load it to a JavaScript array while processing the page.
This would not be ideal but in the absence of server-side processing (which you really should be doing--either PHP or Rails or Perl or whatever your host supports), you could allow directory listing on your images folder. This has security implications.
Then loading e.g., http://mysite.com/rotatingImages should respond with a list of files. You could do this with AJAX, parse out the relevant hrefs, push them onto an array and render your rotating images in JS.
You must send the list of names along with the JavaScript and then iterate through it.
A noted above, you can not access server's system from a client's browser (which is where JavaScript runs).
You have 3 possible solutions:
Create the JavaScript file via some dynamic back-end (php or perl scripts are best for that).
The main JavaScript function could still be static but the initialization of the array used by it (either as a snippet on the main HTML page or a separate .js imported file) would be a php/perl generated URL.
A recent StackOverflow discussion of the topic is at link text
Make an XMLHttpRequest (AJAX) call from your JavaScript to a separate service (basically a URL backed by - again - php/perl backend script) returning XML/JSON/your_data_format_of_choice list of files.
This is probably a better solution if you expect/want/need to refresh a frequently-changing list of images, whereas a pre-built list of files in solution #1 is better suited when you don't care about list of files changing while the web page is loaded into the browser.
An un-orthodox solution - if browsers you care about support animated background images (gif/png), just compile your set of images, especially if they are small sized, into an animated gif/png and use that as background.