I'm trying to get image (jpg file) from node.js and display it in html tag (img), but the picture is not shown (as you can see:).
My node.js which handle the request looks:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended : true}));
app.get('/pictureItem', function (req, res) {
// imagesNames[0].name - contains the name of the image to send (jpg file)
res.sendFile('/images/' + imagesNames[0].name, {root: __dirname })
})
and my js code looks:
$.get("/pictureItem", function(data, status)
{
console.log("got image");
$("#imageId").attr("src", data);
})
what am I missing ?
Your '/pictureItem' route in Express sends an image.
Your ajax call in your client code seems to be expecting to get an URL back, not an image:
$.get("/pictureItem", function(data, status) {
console.log("got image");
$("#imageId").attr("src", data);
});
The usual way you would do this is:
Set $("#imageId").attr("src", data); to an URL that your server knows how to serve the image for.
This will cause the browser to then request that URL from your server.
When your server gets that image request, it will send the image back.
The browser will display the image it got back from the server.
I'm not quite sure what the overall problem is you're trying to solve here (you don't show the overall logic of the operation), but you could just do this:
$("#imageId").attr("src", "/pictureItem");
And, then your existing server route would return the desired image when the browser requests the image from the /pictureItem route.
Have you defined the middleware for static files? If yes you could define a GET method which retrieves the path to a specific image and return that so you can attach it to the src attribute.
Your pictureItem endpoint is return the image file itself. Whereas your src attribute expects a string so it can fetch the image itself.
server.js
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended : true}));
app.use('/images', express.static(__dirname + '/Images'));
app.get('/pictureItem', function (req, res) {
// returns a string as '/images/someimagename.jpg'.
res.send('/images/'+imageNames[0].name);
});
someJavascript.js
$.get("/pictureItem", function(data, status)
{
console.log("Found image on url: " + data);
$("#imageId").attr("src", data);
});
Related
Sorry, I tend to be a bad writer when I have not fully woken up, let me revise.
I am using expressjs with passportjs (local strategy) to manage my server and using connect-busboy to manage file uploading. I do not think passport will play a role in this.
Here is the server code for managing file uploads:
app.post('/upload', isLoggedIn, (req, res) => {
if(req.busboy){
req.pipe(req.busboy);
req.busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
if(mimetype.match(/^image\//)){
var root = path.join(__dirname, "../public/images/");
if(fs.existsSync(path.join(root, filename))){
var name = getUnique(path.join(root, filename));
} else {
var name = filename;
}
var ws = fs.createWriteStream(path.join(root, name), { flags: "a" });
file.pipe(ws);
}
});
}
});
As for my client page, it is used to change a JSON object which will get re-uploaded to the server as a configuration tool. When I upload a new image asynchronously I need to get the filename to update this JSON object while working on it. For uploading from the clients end I am using dropzonejs, which did not require any configuration on my part to work.
So, in summary I upload a number of images via dropzone asynchronously, busboy and fs on my server save the file, and I would like to get the filename returned to my javascript to modify the existing JSON object.
Edit solution:
Thanks to Elliot Blackburn for pointing me in the right direction.
By calling:
ws.on('close', () => {
res.send({filename: name});
});
after file.pipe(ws); to send the response back to the client. On the client side modify dropzone to handle the response like so:
dropzone.on('success', (file, res) => {
console.log(res);
});
Just send it in the normal http response. It'll depend what library you're using but most will allow you to trigger a normal req, res, next express call. From that you can access the file object, and return anything you want.
Something like:
req.send({filename: name}); // name is the filename var set earlier in the code.
Once you've finished editing the file and such, you can get the name and put it into that returned object and your client will receive that as object as the response which you can act upon.
When I use GET, everything works fine. However, I struggle to use POST to achieve the same effect. Here are the code I have tried:
1.
app.post("/download", function (req, res) {
res.download("./path");
});
2.
app.post("/download", function (req, res) {
res.attachment("./path");
res.send("ok");
});
3.
app.post("/download", function (req, res) {
res.sendFile("./path");
});
None of them work. What is the correct way to do this?
EDIT:
I submit a POST request through a HTML form to /download. ./path is a static file. When I use code in method 1, I can see the correct response header and response body in the developer tool. But the browser does not prompt a download.
This might not be exactly what you want, but I have been having the same trouble.
This is what I did in the end:
Client - See EDIT below for updated client code
$http.post('/download', /**your data**/ ).
success(function(data, status, headers, config) {
$window.open('/download'); //does the download
}).
error(function(data, status, headers, config) {
console.log('ERROR: could not download file');
});
Server
// Receive data from the client to write to a file
app.post("/download", function (req, res) {
// Do whatever with the data
// Write it to a file etc...
});
// Return the generated file for download
app.get("/download", function (req, res) {
// Resolve the file path etc...
res.download("./path");
});
Alternatively, have you just tried calling $window.open(/download); from the HTML? This was the main reason why my download did not start. It returned in the XHR and I could see the data, but also did not prompt a download.
*EDIT:
The client code was not accurate, after some more testing it turned out that I only needed to do the following on the client:
// NOTE: Ensure that the data to be downloaded has
// already been packaged/created and is available
$window.open('/download'); //does the download
I am using node.js and the express framework to send a get request for an image by appending the image to the body using $('body').append('<img src="images/image.gif?34567">'). When I send the request, the console is logging GET /images/image.gif?34567 200 1.223 ms, but it won't run the functions inside of my router for the route to that image.
router.get('/images/*', function(req, res) {
console.log('Accessed image folder...')
var requestURL = url.parse(req.url,true);
//ATTEMPT to capture request
if(requestURL.pathname == '/images/image.gif') {
console.log("Fetching image...")
}
});
I was also trying to use the specific route: router.get('/images/image.gif', function(req, res) {, and tried following this example.
How can I make the GET router work when requesting a specific image inside of the images directory?
router.get('/images/:imageName', function(req, res) {
var image = req.params['imageName'];
res.header('Content-Type', "image/gif");
fs.readFile(image, 'utf8', function(err, data){
if(err){
res.end(404);
}
res.send(data)
});
});
Just grab the image name as a parameter, set the content type (you could also do this dynamically based on the requested file extension, for simplicity I only set it to gif), then do an async file load for the image name and return it.
If you are trying to view a image from node server, then you have to use express static . The following code might help you.
var express=require('express'),
app=express();
app.use("/pictures", lib.express.static("./assets/images"));
Here '/pictures' is the route to get image(e.g http:\localhost\pictures) and '/assets/images' is actual path foe image.
If you want to upload the image then you should use any upload module of node as per your requirement.
I'm implementing cache for static serving middleware for Express.js, which works as follows — when request comes, middleware first tries to serve file from filesystem, and if there is none, file is fetched from upstream and stored in file system.
Problem is I don't know how to properly detect “cache hit” event.
staticMiddleware = function(req, res, next) {
// try to read file from fs
filename = urlToFilename(req.url);
stream = fs.createReadStream(filename);
// cache miss - file not found
stream.on('error', function() {
console.log('miss ' + req.url);
// get file from upstream, store it into fs and serve as response
stream = fetchFromUpstream(url);
stream.pipe(fs.createWriteStream(filename));
stream.pipe(res);
});
// cache hit - file is being read
I_DONT_KNOW_WHAT_TO_PUT_HERE(function() {
console.log('hit ' + req.url);
stream.pipe(res);
});
}
So, basically, how can I detect succesful file reading? If I listen to 'data' event, I guess I miss first chunk of data. If I just pipe() it to response, response stream gets closed on error, and I can't serve it with fetched data, and this approach really lacks flexibility. I wonder if there is way to listen for event like fdcreated or opened or similar, or way to push back data I've got in data event, so it will be resent in next data event.
Method createReadStream returns a ReadableStream which also an event open. You can add an event handler for the open event so you will know when the resource is valid before piping:
stream.on('open', function() {
console.log('hit ' + req.url);
stream.pipe(res);
});
Using Meteor.js, how can I serve an arbitrary HTTP response, eg. an image or PDF?
Example 1 - I need to generate PDF reports, which I cannot store in public/ or on a third-party server. Or, the report may be generated live in response to a HTTP GET.
Example 2 - If I have a url like:
/images/myimage.png
I would like to detect that request on the server, read the image from MongoDB, and serve it with the correct headers, so it is available to use with img tags, ie.
<img src="/images/myimage.png">
I do not want to store the images in the /public/ directory, so that I can have more control over exactly what is served and how it is permissioned.
Edit I was also able to get a basic example working using Iron Router.
ImageController = RouteController.extend({
run: function() {
var f = fs.readFileSync("/path/to/image.png");
var res = this.response;
res.writeHead(200, { "content-type": "image/png" });
res.write(f);
res.end();
}
});
Router.map(function() {
Router.route("images", {
path: "/images/image.png",
where: "server",
controller: ImageController // Note - cannot use string here - Iron Router has a dependency on window
});
});
You may write the response code as in any node app, using the middleware:
WebApp.connectHandlers.stack.splice (0, 0, {
route: '/path/to/the/file',
handle: function(req, res, next) {
res.writeHead(200, {
'Content-Type': ...ITEM TYPE... ,
});
res.write( ...ITEM DATA... );
res.end();
},
});
You can use filepicker. In filepicker the upload images is save in the bucket(cloud) and returns the url of that image. You can save the url in your mongo database. and when you want to use that image just use <img src="{{saveurl}}" > .
For more help see the documentation https://developers.inkfilepicker.com/docs/web/