Send image generated in frontend javascript - javascript

I got this third party lib which generates a screenshot.
I want to save this on my server. I'm using Axios.It's probably something with blobs, arraybuffers etc?
How do I send it?
Axios.post('/api/saveimage', { ??? })
Using NodeJs express on backend. How do I save this to a physical image file?

Well at the frontend you need to send it like this:
let formData = new FormData()
formData.append("image", file)
axios.post("/api/saveimage",formData)
At the first step you create a FormData, then you append the file. In this case i named the file image. Now lets go to the next step. You will need multer on your nodejs side.
npm i multer
The first think you need to do, is to create an middleware:
const multer = require("multer");
const whitelist = ["image/png", "image/jpeg", "image/jpg", "image/webp"];
const storeImages = multer.diskStorage({
destination: async function (req, file, cb) {
if (!whitelist.some((type) => type === file.mimetype)) {
return cb(new Error("File is not allowed"), "/");
}
cb(null, "your/destination/path");
},
filename(req, file, cb) {
let [name] = file.originalname.split(".");
cb(null, name + ".png");
},
});
exports.uploadImageStorage = multer({
storage: storeImages,
});
Here watch out: Your destination path should exist. Also dont forget an extension for your file in this case .png
Now you create your route:
const { uploadImageStorage } = require("../yourstorage")
app.post("/api/saveimage", uploadImageStorage.single("image"), (req, res) => {
let file = req.file
let path = file.path
})
Here you need to know at uploadImageStorage.single("image") i used image like i used it in formData.append("image", file) they need to be the same.
Now you can save the path of your file into a database. You can also transform your image with sharp if you want
From my experience if you have folder called static and you have a image inside of it like photo.png you usually get the photo with localhost:3000/photo.png and not with localhost:3000/static/photo.png
You will need to remove static from your path if you have this setup. Otherwise if you try to display the image on the frontend you wont see it.

Related

How to download a zip file from backend server to frontend react [duplicate]

I found a example from expressjs:
res.download('/report-12345.pdf');
to prompt the user for download. But i pass a url as parameter. It not working.
res.download just accepts path to filesystem in local.
For your requirement you can do one of below:
1) use res.redirect({URL})
2) get that file from URL and then send file to client like :
app.get('/', function(req, res){
http.get(URL, function(file) {
file.pipe(res);
});
});
This worked for me
const https = require("https");
const fileName = "the file name" + ".mp4";
https.get(url, function (file) {
res.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
res.set('Content-Type', 'video/mp4');
file.pipe(res);
});
Here select the Content-Type for you file
Here's a list of mostly all content type
In the fileName add the file extension of your file i.e. ( .jpg , .png , .txt)
The first parameter to the res.download() method is the absolute path to the file on the filesystem, not a network URL. So if you say res.download('/report-12345.pdf'); you are trying to download the report-12345.pdf file from the root folder of your filesystem.

Getting the image url uploaded in nodejs

I am using nodejs multer to upload an image file to image uploads directory. After uploading, how can this particular image be displayed in html img tag in client browser. What is the url?
When I type in http://localhost:3000/uploads/1591342432.jpeg, it says cannot get the file.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./uploads/");
},
filename: function (req, file, cb) {
cb(null, Date.now() + ".jpeg");
},
});
const upload = multer({ storage: storage });
router.post("/upload", upload.single("file"), async (req, res) => {
try {
console.log("uploading...");
console.log(req.file.filename);
res.json({ cool: "yes" });
// res.json({ file: req.file });
} catch (error) {
console.log(error);
}
});
It seems you are using multer to upload img to a local folder called uploads.
I will recommend the following tutorial: upload img to firebase
This tutorial uses multer to upload the cloud firebase. Once you upload the image, you will get the link to the image where it is stored on the cloud and the same link you can use on the other server
I think I need to set a static directory:
app.use(express.static("uploads"));
Then I can access the image file as:
http://localhost:3000/1599134489853.jpeg
If you haven't already, you will need to set GET path for the image resource when attempting to fetch via http://localhost:3000/1599134489853.jpeg. For an express app, it appears the current simple/preferred method for returning the file is res.sendFile. Otherwise, you can generate stream and return as demonstrated here.

multer: how to pass variables to next handler

I'm using multer to upload images. The following is my multer configuration:
import multer from "multer";
import * as mime from "mime-types";
import path from "path";
export const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads/");
},
filename: function (req: any, file, cb) {
const name = path.parse(file.originalname).name + "_" + Date.now();
const extension = mime.extension(file.mimetype);
const filename = `${name}.${extension}`;
/**
req.fileInfo = {
filename,
name,
extension
} */
cb(null, filename);
},
});
export const upload = multer({ storage: storage });
I want to get fileInfo object in next handler.
import { upload } from "src/middlewares/imageUpload";
router.post('/imageUpload', upload.single("upload"), async (req, res) => {
//
const filename = req.fileInfo.filename;
});
According to this answer, res.local is the correct place to store variables between middleware and handlers.
But multer diskStorage configuration does not accept res parameter. I tried to store fileInfo object in req but sometimes it works and sometimes it doesn't(req.fileInfo is undefined for some routes, although the code is exactly the same).
How can I pass fileInfo to next handler?
multer middleware automatically sets the property named file on req object which contains the information about the uploaded file and can be accessed in the next middleware, so you don't need to set it your self.
If you still want to do that, you can attach fileInfo object to req object but it will only be available in next handlers where multer middleware is one of the middlewares in the pipeline. So req.fileInfo will be undefined for routes for which request doesn't goes through multer middleware.
You can make every request pass through the multer middleware but if that request doesn't contains any file that should be uploaded, req.fileInfo will be undefined because no file was uploaded by multer.

Write a file to the filesystem then download in Express

Is it possible to use res.download() after writing a file to the filesystem?
router.get('/exportjson', (req, res, next) => {
let json = `{"#dope":[{"set":"","val":"200"}],"comment":"comment","folderType":"window"}`
const file = `${__dirname}/upload-folder/export.JSON`;
fs.writeFile('file', json, 'application/json', function(){
res.download(file);
})
})
I'm not sure I fully understand your question, but I'm assuming you want to be able to save that json data to the path /upload-folder/export.json and then allow the browser to download the file using res.download() at the path GET /exportjson.
You've got a couple of issues. First, fs.writeFile takes a file path as the first argument, and you are just passing the string file. With your code, the data would be written to the current directory as file. You probably want to use the path module and create a path to the file you want to write, like so:
const path = require('path');
const jsonFilePath = path.join(__dirname, '../upload-folder/export.json');
Assuming the code is at routes/index.js, this path would point to the root directory of the project to the file upload-folder/export.json.
The data you want to write is in your variable json, but you have it stored as a string. I would actually leave it as an object:
let json = {
"#dope": [
{
"set":"",
"val":"200"
}
],
"comment":"comment",
"folderType":"window"
};
And then call JSON.stringify on it when you pass it to fs.writeFile as the second argument. You will also need to pass in the utf-8 option as the third argument, not application/json:
fs.writeFile(jsonFilePath, JSON.stringify(json), 'utf-8', function(err) {
In the callback to fs.writeFile, you want to call res.download and pass it the path to the file that you just wrote to the filesystem, which is stored in jsonFilePath (you had this part right, I just changed the variable name):
res.download(jsonFilePath);
Here is the relevant portion of the router file that has code to get everything working correctly:
const fs = require('fs');
const path = require('path');
const jsonFilePath = path.join(__dirname, '../upload-folder/export.json');
router.get('/exportjson', (req, res, next) => {
let json = {
"#dope": [
{
"set":"",
"val":"200"
}
],
"comment":"comment",
"folderType":"window"
};
fs.writeFile(jsonFilePath, JSON.stringify(json), 'utf-8', function(err) {
if (err) return console.log(err);
res.download(jsonFilePath);
});
});
Assuming this file lives in /routes/index.js, the file would be saved at /upload-folder/export.json.
Here is a gif showing how it looks on my machine:

Loop through all files/images in a folder with Angular

I have an app with some products and each product has a gallery with a different amount of images. Each of the images has a name that is completely random / no correlation with the other image names.
Each of the product images are in /src/assets/images/products/:id/.
I need to add the paths to a gallery component but I can't loop through them because the names are random. Is there any way to just loop through each file from a folder using only Angular? If not can I do it on the back-end without renaming the files? I'm also running the app on a Node.js back-end if that matters.
You can't do that with frontend.
What you need to is using your back-end and return file in it.
You are using NodeJs as back-end so can use the fs.readdir or fs.readdirSync methods.
fs.readdir
const testFolder = './images/';
const fs = require('fs');
fs.readdir(testFolder, (err, files) => {
files.forEach(file => {
console.log(file); // use those file and return it as a REST API
});
})
fs.readdirSync
const testFolder = './images/';
const fs = require('fs');
fs.readdirSync(testFolder).forEach(file => {
console.log(file);
})
Read the full documenation, it may help you to how you can proceed.

Categories