How to fetch mutiple images from express api's into react application? - node.js

I am using mern stack to program an application. I used multer package with express for file uploading and uploaded images in a directory in node.js application. Now i want to fetch the image from that directory. How can i do this? I have found
res.sendFile()
but there are cases when i will need to fetch multiple files from server at once. I also have found just sending path from api to react and serving from a folder into react which i don't find secure? how do i go about it?

You should decouple the back end from the front end, which means, separate the express part from the React part and make simple API, express also can serve files as static(search google for static file serving), then call the API from your React App. Just give the React App Image URL like example.com/static/image1.png(<img src={"example.com/static/image1.png"} />)

I ended up using streams for my problem the following snippet might come in handy for some one with similar issue.
const fs = require('fs')
const stream = require('stream')
app.get('path',(req, res) => {
const r = fs.createReadStream('path to file') // or any other way to get a readable stream
const ps = new stream.PassThrough() // <---- this makes a trick with stream error handling
stream.pipeline(
r,
ps, // <---- this makes a trick with stream error handling
(err) => {
if (err) {
console.log(err) // No such file or any other kind of error
return res.sendStatus(400);
}
})
ps.pipe(res) // <---- this makes a trick with stream error handling
});

Related

Saving An Image file to Assets folder in React App

I am trying to upload a image in my react app and save it in my assets folder.
I have the DataUrl for the image , but when i am trying to write the dataurl to an image file using fs.writefile(), i am getting below error
var normalizeFilePath = (path: string) => (path.startsWith('file://') ? path.slice(7) : path);
|
| type MkdirOptions = {
ModuleParseError: Module parse failed: Unexpected token (30:29)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See ht tps://webpack.js.org/concepts#loaders
| };
my application is a gatsby -react Application.
on clicking the submit button , submit handler is called to write the data to file.
const submitHandler = (event) => {
console.log(event.target);
console.log(files.target);
fs.writeFile(`../assets/images/testimonialImage/${files.target.files[0].name}.png`, files.target.files[0], function (err) {
if (err) throw err;
console.log('Replaced!');
});
}
Tried using saveAs function but its downloading file to downloads folder.
What i need is , when i upload the file in frontend , it should save it in the assets/image folder.
As i am not having any backend for my app.
Your approach of uploading a file in frontend and saving it to assets/image is only going to work in a development environment. If you want it to work in production environment too, you NEED a backend. It could be a simple node.js server which saves the file to a folder.

How to use node:fs inside of a vue app to save images into source directory

I'm building a personal portfolio website using Vue.js, and I'm attempting to build a form to allow me to add to my portfolio later. I'm storing the text data in firebase, but I also want to be able to upload and access pictures. I'm attempting to upload through a form and save with node:fs with the following
import { writeFile } from 'node:fs'
export function saveImages (data:FileList, toDoc: string) {
const reader = new FileReader()
const imageNames = []
console.log(toDoc)
for (let i = 0; i < data.length; i++) {
imageNames.push(toDoc + '/' + data[i].name)
reader.readAsBinaryString(data[i])
reader.onloadend = function (e) {
if (e.target?.readyState === FileReader.DONE) {
const imageFile = e.target.result as string
if (imageFile) {
writeFile('./assets/' + data[i].name, imageFile, 'binary', (err) =>
console.log('was unable to save file ' + data[i].name + ' => ' + err)
)
}
}
}
}
return imageNames
}
When I attempt to call saveImages, I get the error
ERROR in node:fs
Module build failed: UnhandledSchemeError: Reading from "node:fs" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.
As pointed out by the comments on your answer, the Node.js-fs-module is cannot be used in the frontend. Here is why:
While developing your vue.js-app, you should remember that you always have to run a development server in order for the app to compile to a browser-readable format. The resulting page will not be delivered as some .vue-files and .js-files but everything will be bundled into an html-file and some additional .js-files.
While running the development server, the source directory of your app is 'lying' on a server, but this is not even the directory that is delivered to the browser.
In a production server, there will be static assets built out for your vue.js-app, which does also only contain .html- and .js-files.
When a client (browser) accesses a route, some static files will be delivered to the browser, and all the code you are writing in your .vue-files will be run on the client's machine, not on a server. So you cannot interact with server-side directories.
Therefore, you should look into a backend server framework, which you can connect to your frontend to allow users to upload files to a server, and those files would be saved on the server. You will then set up your vue app to communicate with the backend. Here are some additional resources:
Node modules with vue: StackOverflow
Express.js: popular backend framework for Node.js
Express.js: Deliver files
Blog article on Express.js file upload (Attacomsian)
You might also want to take a look on how to send static files with express, because once the files are uploaded and the server receives them, it could store them into a static-directory, where you could access them without having to use separate API-routes.

React fullstack architecture: When adding a react front-end to a node/express application, what aspects does react's state generally handle?

I have a fully built node/express application that I want to add react to in order to practice that relationship in full stack applications. I've built apps in react before, and in node, but never together and I am confused about how react fits into the MVC architecture.
In a react-node full stack application does react state then handle all of the data I was previously passing into my ejs views?
I have been looking through tutorials on full stack applications with node and react, but they only seem to go into issues like how does react fetch data from the back end, or how to set up the configuration,
but I get that part, I just don't understand what react does in a full stack application, what part of the model-controller-view architecture of a node/express backend app does react take over? How are the responsibilities split between the backend and front end?
So for example, I'm working with a reddit-clone type app so when you click on a post title to see the post my controller queries the database for that post and then passes it to the view as {post}:
show(req, res, next){
postQueries.getPost(req.params.id, (error, post) => {
if(error || post == null){
res.redirect(404, "/");
} else {
res.render("posts/show", {post});
}
});
},
So when I add a front-end with react, would that {post} object then be something handled by react? So react would fetch that data and use it in a post component to create what is currently my view show.ejs file?
So when I add a front-end with react, would that {post} object then be something handled by react? So react would fetch that data and use it in a post component to create what is currently my view show.ejs file?
Yes. The show.ejs would be a React view or a page that contains a component to handle how to show it.
To simplify:
React -- is a virtual DOM, so it'll swap views/containers/components in and out based upon events (like clicking a button), which in turn, will: retrieve, display, manipulate and/or send data to the API. In development, it is completely separate from your back-end. All the routing will be handled by a front-end router package. In production, all of the front-end src code is compiled into a dist or build folder that contains your assets (images, fonts, css) and most importantly bundle.js file(s) that are then served by express.
Express + some database -- will act as your API where it'll CRUD data based upon the front-end request(s). If your app is a MPA (multiple page application), then a common practice is to delineate your back-end routes from your front-end routes with a /api/ prefix. In production, if express doesn't recognize the route (it's not a /api/ request), then it'll fall back into the front-end bundle.js file where it'll be handled by the front-end router.
See a working example here: https://github.com/mattcarlotta/fullstack-mern-kit (client is the frontend, everything else is the backend)
Or
See a working codesandbox (where I'm making a GET request to an API that returns json):
For your example above, your show controller will just be sending JSON (or a string message) back to the frontend (redirects will happen on the frontend via a router -- like react-router-dom):
show(req, res, next){
postQueries.getPost(req.params.id, (error, post) => {
if(error || post == null){
// res.status(404).send("Unable to locate posts.");
res.status(404).json({ err: Unable to locate posts });
} else {
res.status(200).json({ post });
}
});
},
You can even simplify the above using async/await:
const show = async (req, res, done) => {
try {
const post = await postQueries.getPost(req.params.id);
res.status(200).json({ post });
} catch(err) {
// res.status(404).send("Unable to locate posts.");
res.status(404).json({ err: Unable to locate posts });
}
};
And then the React front-end handles the response.

Node.js Express save SVG file stream to file

I am new to Express and I need your help.
How to save SVG on server using Express?
const qr = require('qr-image');
const fs = require('fs');
exports.qr = function (req, res) {
var code = qr.image(new Date().toString(), { type: 'svg' });
// I would like to do something like this:
fs.writeFile('qr.svg', code, (er)=> console.log(er));
// and download using express.static
res.type('svg');
code.pipe(res);
};
Currently I am returning image as a stream and it works fine.
I have an api with mongodb built on Express and I would like to store QR Codes on the server side. Api is for the application built with Xamarin managing event tickets.
QR images are going to be downloaded more than once, that's why I would like to put them on server.
Maybe better way would be to store them with SQLite locally on the client device? Or maybe I should just send json data to be parsed into SVG?
How do you think?
At the moment I am not implementing db locally.
After some time when I went back to the topic I found the solution.
You need to add new action to your pipe. Simple as that:
var code = qr.image(ticket.code, { type: 'svg' });
code.pipe(fs.createWriteStream('i_love_qr.svg'));

Simple file upload with Node.js

I am building a node.js application that uses pdf.js to read pdf files, but much like other js, pdf.js does not allow cross origin requests. So, I need a way to save files selected with a file input to my pdf directory. I'm not so great with node so make it as simple as possible if you can.
Here is a basic idea of what you need:
1st, require and use module 'connect-multiparty'. This will expose the req.files object in node.
var multipart = require('connect-multiparty');
app.use(multiparty({});
Then, in your controller method, require the 'fs' module, and use it to save the uploaded file.
var fs = require('fs');
fs.writeFileSync("myFileName", req.files.file.ws.path, function(err) {
if(err) { console.log(err); }
else { console.log("file uploaded"); }
});
Being familiar with node will help, but the two basic libraries you need to perform this are the aforementioned https://www.npmjs.com/package/connect-multiparty and http://nodejs.org/api/fs.html
edit: see the link in the comments below. this answer is incomplete and is better explained in the link

Resources