Files stored to public folder get reset node js - node.js

In my node js application I am turning user data entered through a form into a js object and then storing that js object as a json file in the public folder of my ejs server. This works all well locally on my computer however when I use Heroku all the files that get stored into the server from form requests reset after a while.
Below is what I'm going to store json files
fs.writeFile(
__dirname + "/public/" + "AddonPosts/" + addonFromFile.name + ".json",
JSON.stringify(addonFromFile),
function (err) {
if (err) throw err;
}
);
Is there any way to write to my server without it constantly resetting? Additionally would there be an easy way to then download that folder I have written to?
Thanks

heroku Free tier does not save the files that are uploaded/Newly Created when your app is running. It resets your app to the stage how it was uploaded.
In short, dynamic uploads/Saving are not possible.
Alternative way: Use mongodb atalas[Free 500mb] to store your data

Related

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.

Send multiple images from node js to frontend

I am implementing a gallery where i wanted to show all images in a page - Reactjs or Angular
How can i send multiple images to frontend from NODE? I was able to send one image file saved in a folder in nodejs.
Below is the code for sending single image - im able to see that image using POSTMAN
Note : here im fetching the image name from a table - These images are there in event folder(image1.jpg, image2.jpg...)
console.log(req.files);
const {id} = req.params;
var sql = "SELECT image from users_image where id = ?";
var query = db.query(sql, [id], function(err, result) {
if(err){
console.log("Error ", err);
res.status(500).send(err)
} else {
const fileNameAndPath = result[0].image; //image1.jpg
if(err) res.status(500).send(err);
res.sendFile(fileNameAndPath, { root: './public/images/upload_images/event' })
}
});
}
But im not able to send multiple images using sendFile() as it does only single image.
How can i implement this?
is it possible to get the preview using postman if i sent multiple images from node?
I could find many example which reads images from server but to html files in same backend directory. They are not sending the response to frontend, so that we can get the image and show in out ui built in react or angular.
Is my approach correct? Planning to deploy frontend, backend and DB in same server
If I understood correctly, your images are in a folder that is located in your NODE JS backend folder and you want to send multiple images depending on request from your REACT Side.
To do this you can make the folder where you stored those images in backend as a public static folder.
In your entry point of Node Application,
app.use(express.static(__dirname+'/<foldername>'));
Now suppose you have a image inside the folder named flower.jpg, car.png and jolly.jpg that you want to send.
The URL for these images will be :
localhost:<port number>/<image name>
For example :
localhost:3000/car.png
localhost:3000/flower.jpg
Now to access from your react code all you need to do is, replace localhost with the IP of your NodeJS Server.
Something like : 172.32.112.12:3000/car.png
You just need to make sure that the image names are not something common and easy.
My image names are something like 1639873167172-464191690.jpg. I change it while I store it on database.
If the photos are already hosted on your server, you should send an array of urls to the photos. In the frontend, you can loop through the array of urls and display the images using image tags.

how to read image stored in mongodb and display in nodejs

I am making a nodejs app which displays pictures stored on servers ,I was using multer to store pictures in the same directory and I was using mongodb as my database to store the path of the picture that user uploads , and then i read the path and displayed the pictures something like this,
<div class="post-image flex">
<%var imagesource='../'+postobj.blob.path%>
<div>
<img class='onbottomimage' src="<%=imagesource%>" >
</div>
</div>
everything was working fine locally.
but now I have deployed my app to heroku and found out I cannot store pictures on heroku as the user uploads them, I still have the pictures stored in mongodb in base 64 format something like this
image
:
Binary('/9j/4AAQSkZJRgABAgEAYABgAAD/7gAOQWRvYmUAZAAAAAAB/+EUI0V4aWYAAE1NACoAAAAIAAcBMgACAAAAFAAAAGIBOwACAAAA...', 0)
how do i convert them back to pictures and display them in img tag in ejs, or what other options do i have ,I dont want to change heroku but still be able to display the pictures that the user uploads.
If you are storing your uploaded images in the Heroku server, it is an utter waste. Because Heroku Dyno will restart every day which will delete all the extra added data other than data stored during deployment time.
I think you are using express.
let fs=require("fs")
let yourBuffer=//retrieve that buffer and store into this(yourBuffer) variable
let buffer = new Buffer.from(yourBuffer)
fs.writeFile(`location to storeimage/imagename.yourimageextension`, buffer, "binary", function (err, written) {
if (err) console.log(err);
else {
console.log("Successfully written");
res.sendFile((__dirname + `location of image/imagename.yourimageextension`))
}
});
I think a better solution would be using a 3rd party storage provider, aws s3 for example, and only store image url in the database

How to accept a file and then store it in cloud storage

I am using expressjs (all newest versions of express, node, and npm). I have create a route such as this:
router.post("/", function(req, res, next) {
});
This route will need to be able to have a file (image/video/docx,etc) uploaded and needs to then be stored on a cloud storage service (Google Storage). I do not want to store anything on the server that express is running on, just want to receive the file and pass it on over to Google Cloud Storage. I see there are some libraries which do this in addition to express, but I couldn't not find how to do it using just express.
I think your clients might be able to upload directly to GCS by constructing a HTML form. Basically you can create a signed url and embed it in the form and then on submit, the upload goes straight to GCS and your app doesn't need to handle it at all.
See: https://cloud.google.com/storage/docs/xml-api/post-object

Nodejs - writing and saving files

I am investigating how to download files to a user's local machine but I'm not quite sure what I need in order to do this. I'm using Nodejs and Express with Angularjs on the front-end.
User's can write text into a textarea and it's this text that will be written to the file.
To do this I have:
...
fs = require('fs');
fs.writeFile('filename.txt', textarea.text, function (err) {
if (err) return console.log(err);
res.send(200);
});
...
Once the file is created how do I get it to download on the user's machinea?
Use res.download
res.download('filename.txt');
http://expressjs.com/4x/api.html#res.download
If you don't need to store the file on the server, you could just sent it back to the user directly:
res.attachment('filename.txt');
res.set('Content-Type', 'text/plain');
res.send(textarea.text);
This is not only simpler but also improves performance (no disk i/o) and more secure (no untrusted files on your server).

Resources