0

I need to display in my server an html containing some text and stuffs, which are not important here, and the first image found inside the folder given as parameter.

I found another answer where fs.readFile was used to retrieve the html file drectly, with the image already in there, but in this case I need to build an html for every image.

I've tried this, but it doesn't show any image:

var http = require('http');
const fs = require('fs');

function read_dir(req, res, path="./images") {
    
    let image_urls = fs.readdirSync(path);
    let src = path.split("").slice(1).join("");

    let image = `<img id="image" src="http://localhost:8888${src}/${image_urls[0]}">`;
 
    res.end(image);
}

function onrequest(request, response) {
    // Programs what is going to be sent back to the browser.
    console.log("HTTP request received");

    // Parses command line arguments
    var myArgs = process.argv.slice(2);

    response.writeHead(200, 
        {"Content-Type": 'text/html'}
    );
    response.write(`<h1>SLIDESHOW AREA</h1>`);

    read_dir(request, response, myArgs[0]);
}

// The http.createServer() method turns my computer into an HTTP server.
var server = http.createServer(onrequest);

// The server.listen() method creates a listener on the specified port or path.
// server.listen(port, hostname, backlog, callback);
server.listen(8888);

console.log("Listening on http://localhost:8888/");
Kyle
  • 113
  • 3
  • 13

2 Answers2

1

Okay, so I found out what was missing. If you're one like me that understand really poorly servers, this might be helpful.

<img src="http://localhost:8888/image/jpeg/campus1.jpg">

When the server reads the image src, it sends a GET request with url /image/jpeg/campus1.jpg. Right now the server can display HTML elements, but it cannot display JPEG elements, which is fundamental here.

It's really subtle, the image has to be read from its folder, and be set up correctly before it can be displayed.

So, the correct way to do it is to make a route inside the server that reads images and tells the server that they are of type 'image/jpeg'. At that point, the images are ready and baked to be read by the HTML.

var http = require('http');
const fs = require('fs');

let routes = { "/": main, "/image": fileRouter }

function main(req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});

    res.write("<h1>HI</h1>");
    res.write("<h2>Here's an image</h2>");
    res.end(`<img src="http://localhost:8888/image/jpeg/campus1.jpg">`);
}

function fileRouter(req, res) {
    let path = req.url;
    console.log(path);

    fs.readFile("."+path, function(err, data) {
        if(err) {
            res.writeHead(500, { 'Content-Type' : 'text/plain' });
            res.end('500 - Internal Error');
        } else {
            res.writeHead(200, { 'Content-Type' : 'image/jpeg' });
            res.end(data);
        }
    });
}

function onrequest(req, res) {
    //Parse Request
    let url = req.url;
    let route = url.split("/")[1];
    console.log(req.method, req.url);
    
    //Route Request
    if (typeof routes["/" + route] === 'function') { 
        routes["/" + route](req, res);
    } else {
        res.writeHead(404); //not found
        res.end();
    }
}

var server = http.createServer(onrequest);

server.listen(8888);

I wish programming wouldn't require always my head to get dislodged, things don't always make sense, I don't get sometimes why people designed things this way. But well, also love's not always easy. Have a nice day everyone!

Kyle
  • 113
  • 3
  • 13
  • Great answer, and yes programming is often pretty stupid. So many systems, poorly explained working together. In the old days, you could work backwards much more easily. Everything is very complicated now. Your program may break and it might be 3-4 layers down in the abyss to figure it out. Best of luck. – serraosays Jun 03 '21 at 05:15
0

This tag <img id="image" src="http://localhost:8888${src}/${image_urls[0]}"> are trying to access to your server a the "http://localhost:8888${src}/${image_urls[0]}" url.

So you need to serve it for the browser to be able to download it.

An jpeg image is served with the 'Content-type: image/jpeg'header, but in the case of large images you need to make a more complex work, like cache memory, streaming, things like that; or the load time of your page will drop down easily.

It is recomended to use services like cloudinary to serve this type of content.

Ulises
  • 539
  • 3
  • 9
  • But I've seen it happening with a 'Content-type: text/html' before: https://stackoverflow.com/questions/44354877/how-to-serve-image-from-node-server-without-express – Kyle Nov 01 '20 at 10:11