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

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.

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.

Files stored to public folder get reset 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

How to fetch mutiple images from express api's into react application?

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
});

Location of Mirage files in ember addon

I have an Ember addon which is supposed to handle a request to return some data. The main app needs to use this addon, so that requests to retrieve this data are retrieved from mirage. At some point in the future this needs to be disabled in live environments (but not for the time being)
My question is where the mirage directory (and its subdirectories such as factories, fixtures, models, routes etc) should be located in an addon. Should it be in the project root or elsewhere, such as in the app or addon subdirectory?
I have run:
ember install ember-cli-mirage
which creates some files in \tests\dummy\mirage
Creating the files in this directory doesn't seem to work:
/tests/dummy/fixtures/mydata.js
export default [{
"title": "Some data here"
}]
/tests/dummy/routes/mydata.js
class MyDataRoutes {
constructor(routerFnc, route, db) {
routerFnc(route + '/', ({db}) => {
return db.mydata;
});
}
}
export default MyDataRoutes;
/tests/mirage/config.js:
export default function() {
// this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server
this.namespace = 'api'; // make this `api`, for example, if your API is namespaced
this.timing = 100; // delay for each request, automatically set to 0 during testing
new MyDataRoutes(this.get, '/content/mydata', this.db);
}
This is the right place.
You will then be able to use your mirage endpoints either in your tests or in the dummy app directly.
If you want an example of how that would all work together, you can have a look at the repo for ember-power-select https://github.com/cibernox/ember-power-select. They have mirage as well as nice tests in place.

Download multiple files from NodeJS Server

I am trying to support download of multiple files from my Node js server to the client. With the below logic implemented in my NodeJS server, I can support sending of single file to the client.
res.download('group_documents/sample1.pdf','sample1.pdf', function(err){
if (err) {
console.log(err);
} else {
// decrement a download credit etc
}
});
How can i rewrite the above server logic to support downloading multiple files using single request from the client (browser or curl request)?
On web browser you can not download multiple files at a time.
But you can download archived file of all required files.
Using express-zip npm package you can do it easily.
https://github.com/thrackle/express-zip
Install express-zip.
npm install express-zip
Use following code :
res.zip(files);
files is an array of objects.
Each object should be :
{ path : 'path/to/file', name : 'fileName'}
if your target clients are web browsers, then you can't, as the http protocol does not allow for multiple downloads for a single request.
If you really need to do this, then you'd need to either write a custom client application, or (more simply) zip the files into some archive before transmitting them.

Resources