Whenever I'm hitting the endpoint, I keep getting empty file while locally generated file is correct and contains all the fields I need. I've tried piping directly to response but I would be getting:
Cannot pipe, not readable
Of course there might be something I'm doing wrong.
Similar question.
const PORT = 3000;
const express = require('express');
const fs = require('fs');
const csv = require('fast-csv');
const app = express();
app.listen(PORT, () => {
console.log(`Express server is listening on ${PORT}`);
});
app.get('/rates/csv', (req, res) => {
let ws = fs.createWriteStream(__dirname + '/tmp/rates.csv');
csv.write([
["a", "b"],
["a1", "b1"],
["a2", "b2"]
], {headers: true})
.pipe(ws);
console.log('FILE SAVED');
res.download(ws.path, 'rates.csv')
});
You can't pipe a writable stream to another writable stream.
https://medium.freecodecamp.org/node-js-streams-everything-you-need-to-know-c9141306be93
Related
I'm trying to make an API using express in nodejs.
This api should get a request with a photo and post that photo to firebase storage.
The main problem is that for some reason the body of the requests I send are empty.
This is the code for the server:
const express = require("express");
const morgan = require("morgan")
const cors = require('cors')
const app = express();
// Settings
app.set('port', process.env.PORT || 3000)
app.set('json spaces', 4)
// middleware
app.use(morgan("dev"))
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.use(cors({origin: "http://localhost:3001"}))
// routes
app.use(require("./routes/index"))
app.listen(app.get('port'), () => {
console.log("Server using port " + app.get('port'));
});
Routes
const { Router } = require('express')
const router = Router()
router.post('/postImage', async (req, res) => {
try {
const image = req.body
console.log(image) // Here I only get an epty object "{}"
return res.status(200).json(image)
}
catch(error) {
console.log(error)
return res.status(500).json({error})
}
})
module.exports = router
Client side
const postImage = async (image) => {
console.log(image) // Here I get the image data
const response = await fetch("http://localhost:3000/postImage", {
method: "POST",
body: {message: "image"}
})
const data = await response.json()
}
I've tried using body-parser but it seems to be deprecated
you have to send an image from the front end in formData.
const data = new FormData();
data.append('myFile', 'Image Upload');
In back end use multer to upload file to server.
first install multer by : npm i multer
const multer = require("multer");
//Configuration for Multer
const upload = multer({ dest: "public/files" });
app.post("/api/uploadFile", upload.single("myFile"), (req, res) => {
// Stuff to be added later
console.log(req.file);
});
Here is a proper Guide to upload file using multer express js
I have been attempting to respond to a client-side request with Node.JS. I have discovered Node JS - call function on server from client javascript, which seems to explain what I want, except that I can't seem to translate it to my program.
Here is the request via POST in index.html:
$.post("/", {data: 'hi'}, function(result){
$("body").html(result);
});
what I was hoping it would do would be write the result of the call, from my server.js (Node):
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/*', (req, res) => res.sendFile('static/index.html', { root: BUILDPATH }));
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
try this code:
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/', (req, res) => {
res
// best practice is to always return an status code
.status(200)
// just return an json object
.json({"msg": "ok, it all works just fine"})
});
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
The issue is, is that the only route your Node server listens to is the one you define with /*. As you can see, that route returns your index.html file to the client. You did not specify a route that listens for a request that comes from the client.
To solve the issue, you will have to define a route that listens on a specific route for the request you are trying to make from your client.
I see you are using ExpressJS. here is the documentation on writing routes.
I need to handle some request without content-type as binary file
const app = express();
app.use(bodyParser.raw({type: (req) => !req.headers['content-type'], limit: '500mb' }));
those file can be huge (eg. 500 MB).
I want to read req.body as stream for don't wast memory, but bodyParser.raw() make req.body as Buffer.
How handle req.body as Stream?
You can use stream to handle huge file.
Express http request is a readable stream, you can pipe the request binary to file, but make sure the output is also a writable stream.
Example code:
const fs = require('fs');
const path = require('path');
const express = require('express');
const app = express();
app.post('/', (req, res, next) => {
req.pipe(fs.createWriteStream(path.join('./uploadFiles', Date.now().toString() + '.mp4')));
req.on('end', () => {
res.end('Upload complete');
next();
})
})
app.listen('3000', () => {
console.log('Server listen to port 3000');
})
I am trying to download array of objects in .csv format. below is the code snippet which converts an array to .csv and get stored in the file file.csv.
let downloadHelper = function(records){
let csvwriter = require('csv-writer');
createCsvWriter = csvwriter.createObjectCsvWriter;
const csvWriter = createCsvWriter({
path: './file.csv'
csvWriter.writeRecords(records).then(() => {
console.log('Done');
});
}
I need to download the file.csv to my local. tried using requests, didn't help as it is accepting only http requests. no clue, how to proceed..... Please help
You did not provide us a lot of information. But with Express you could do:
app.get("/", (req, res) => {
res.download("./file.csv", "your-custom-name.csv");
});
If this does not help you, please provide more info about the context, framework you are using and what front.
Thank you
For example, you can use Express like this:
// Libs
const express = require('express');
const http = require('http');
const path = require('path');
// Setup
const port = 8080;
const app = express();
const httpServer = http.createServer(app);
// http://localhost:8080/download
app.get('/download', (req, res) => {
res.sendFile(path.resolve(__dirname, './file.csv'));
});
// http://localhost:8080/csv/file.csv
app.use('/csv', express.static(path.resolve(__dirname, './csv_files/')));
// Run HTTP server
httpServer.listen(port, () => console.log('Server is listening on *:' + port));
If you run this snippet, you can open http://localhost:8080/download and ./file.csv would be downloaded.
Following part of code is responsible for that:
app.get('/download', (req, res) => {
res.sendFile(path.resolve(__dirname, './file.csv'));
});
Or if you want to give access to the whole directory ./csv_files/ you can do this:
app.use('/csv', express.static(path.resolve(__dirname, './csv_files/')));
Just create ./csv_files/foo.csv file and go to http://localhost:8080/csv/foo.csv.
Does it make sense to you?
PS Working example:
// Libs
const express = require('express');
const http = require('http');
const path = require('path');
const fs = require('fs');
// Setup
const port = 8080;
const app = express();
const httpServer = http.createServer(app);
// http://localhost:8080/download
app.get('/download', (req, res) => {
const filename = path.resolve(__dirname, './file' + (new Date()).getTime() + '.csv');
fs.writeFileSync(filename, 'foo,bar,baz');
res.sendFile(filename);
});
httpServer.listen(port, () => console.log('Server is listening on *:' + port));
I am using supertest to test get requests to mLab app. If I do a regular GET request with postman I receive this:
{"_id":"5b169a9951573c50d9682d52","text":"First test note","title":"Test1"}
But the response received in the test adds slashes before each quote:
{\\"_id\\":\\"5b169a9951573c50d9682d52\\",\\"text\\":\\"First test note\\",\\"title\\":\\"Test1\\"}
This is my test file:
const server = require("../../app/server");
const request = require("supertest")(server);
describe("routes: index", () => {
test("should respond as expected", async() => {
const app = request("http://localhost:8000");
const response = await app.get("/notes/5b169a9951573c50d9682d52");
expect(response).toEqual("First test note");
expect(response).toEqual("Test1");
});
});
This is my server
const express = require('express'); // node module
const MongoClient = require('mongodb').MongoClient;
const bodyParser = require('body-parser');
const db = require('./config/db');
const app = express();
const port = process.env.PORT || 8000;
app.use(bodyParser.urlencoded({
extended: true
}));
MongoClient.connect(db.testUrl, (err, database) => {
if (err) return console.log(err)
require('./routes')(app, database);
app.listen(port, () => {
console.log('We are live on ' + port);
console.log(process.env.PORT);
});
})
module.exports = app;
I haven't been using supertest myself, but a brief look at your code and documentation immediately shows several issues.
First of all, what you see is what your test framework reports to you - it is a string representation of the json object. It is correct.
What is not correct is how you try to handle the response. Check the documentation:
https://www.npmjs.com/package/supertest
I think, you may solve the problem by
1) setting the expected type
2) and by accessing the body member of the response
const response = await app.get("/notes/5b169a9951573c50d9682d52").set('Accept', 'application/json');
expect(response.body.text).toEqual("First test note");
I hope, this works.