Unable to upload a file express(NodeJS) - node.js

I was facing this tiny issue in a sample NodeJS application I was creating, that I always receive req.files as undefined even though I am uploading a file via postman.
Here's the code:
import express from 'express';
import http from 'http';
let app = express();
app.post('/', function(req, res) {
let files = req.files;
res.send(files);
})
app.listen(process.env.PORT || 8000, () => {
console.log(`Started on port 8000`);
});
export default app;
And here's how I am sending the file via postman:
But I still get and empty response and also as logging on cmd I get the output as undefined:
Would be greatful if anyone could help.

If you want to upload files, I recommend using multer: https://www.npmjs.com/package/multer
But if you don't want to use multer or bodyparser, you can stream the data:
req.on('data', data => {
console.log(data);
});
You can pipe the stream to write to file. check fs documentation.

Related

How to request a csv file from a url via nodejs?

I'm looking for a way to request a csv file from any url to save it then. If possible only using fs, http, request and express modules.
For testing I tried it with
request('http://localhost:3000/data1.csv').pipe(fs.createWriteStream('data2.csv'))
but i always get as a resonse (data2.csv)
<pre>Cannot GET /data1.csv</pre>
Simplified Code
const fs = require('fs')
const request = require('request')
const express = require('express')
const app = express()
app.listen(3000)
app.get('/download', (req, res) => {
request('http://localhost:3000/data1.csv').pipe(fs.createWriteStream('data2.csv'))
})
The file data1.csv is saved in the root of my project folder. But is this also the root of my nodejs server from where I started it?
What I'm doing wrong here?
Thanks!
You need to have an explicit handler that returns data1.csv:
app.get('/data1.csv', (req, res) => {
res.sendFile('data1.csv');
});

Unable to receive files in request using express-fileupload

I use a REST client to test my app (Insomnia and postman). My app literally does nothing:
const express = require('express');
const app = express();
const fileUpload = require('express-fileupload');
app.use(express.json())
app.use(fileUpload());
app.post('/', fileUpload(), function(req, res) {
console.log(req.files)
res.send('a')
});
const PORT = 9999;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
Whenever I try to upload a file to this service req.files is undefined. I took this code from express docs page and from a few stackoverflow questions and it just doesn't work for me. Content-length is good (40k seems right)
Content-type is auto set by my REST client. Do I have to change this?
I tried simply printing whole request object and body is empty and files is not even present there
So for anyone wondering. fileupload requires form-data Content-type. Moreover, it also requires a file to have a "key" within this form-data. It's a shame documentation fails to mention this.
Just do one thing: remove file fileUpload() from post endpoint and check, find below code for your reference.
app.post('/', function(req, res) {
console.log(req.files)
res.send('a')
});

Piping (proxying) an image stream in express produces an empty box

I am trying to pipe an image response from an internal API, using NodeJS Express to an external endpoint. I.e. proxying an image.
This is what I have tried, but I keep getting an empty box instead of the image:
app.get('/image', (req, res) => {
res.setHeader('Content-Type', 'image/png');
request.get(`http://localhost:8080/image`).pipe(res);
// Also tried reading from a file and not the endpoint
//to make sure it's not a problem with "request" library with same results
//fs.createReadStream('./image.png').pipe(res);
});
Using browser dev tools I can also see that the size of the empty image I get on the external endpoint is bigger then that of the working image got from the internal endpoint.
Accessing the endpoint from "Postman" seems to give the image without problems, but accessing from Firefox says that the image has errors.
So it seems to be some kind of an encoding issue which I can't seem to figure out how to fix. Please help.
Can't reproduce your issue. The below example works fine. Testing environment:
Microsoft Edge 86.0.622.38
E.g.
server-internal.ts:
import express from 'express';
import fs from 'fs';
import path from 'path';
const app = express();
const port = 8080;
app.get('/image', (req, res) => {
console.log('internal server /image');
res.setHeader('Content-Type', 'image/png');
fs.createReadStream(path.resolve(__dirname, './image.png')).pipe(res);
});
app.listen(port, () => console.log('HTTP server is listening on port:', port));
server-external.ts:
import express from 'express';
import request from 'request';
const app = express();
const port = 3000;
app.get('/image', (req, res) => {
console.log('external server /image');
res.setHeader('Content-Type', 'image/png');
request.get(`http://localhost:8080/image`).pipe(res);
});
app.listen(port, () => console.log('HTTP server is listening on port:', port));
Access http://localhost:3000/image, got the image correctly.
The logs of the internal server:
HTTP server is listening on port: 8080
internal server /image
The logs of the external server:
HTTP server is listening on port: 3000
external server /image
source code: https://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/64302729
Thank you slideshowp2 for taking your time and pointing out that, my provided code should indeed work.
It would have been impossible to figure out the issue with the info that I gave.
I was using "livereload" middleware in my project.
This middleware intersects all the responses coming from my server and tries to inject the liverelad script into them.
By default it is configured to ignore responses for endpoints ending with ".png" and other image and binary formats.
Adding ".png" to the endpoint path, solved the issue.
app.get('/image.png', (req, res) => {
request.get(`http://localhost:8080/image`).pipe(res);
});

How to upload file from nodeJS to nodeJS

I have 2 nodeJS services and I would want to upload file in a dir, from one NodeJS (backend) to another NodeJS(backend). The receiver nodeJS is an express app.
Looking for some working code sample.
PS: Couldn't find any code samples in search, since everywhere it was Multer from client to server uploads that receives multipart/form-data.
Uploading file using POST request in Node.js
Receive the file first as you correctly said using Multer. Then, you may either save the file to a temporary directory before uploading it again or just send the file as-is.
You need to setup a server running with Multer on the 2nd server that wishes to receive the file.
const express = require('express');
const app = express();
const upload = multer({ dest: 'files/' });
app.post('/upload', upload.single('file'), (req, res) => {
res.sendStatus(200);
});
app.listen(3001);
Then on the server you wish to send the file from, do something like this:
const request = require('request');
const req = request.post('localhost:3001/upload', (err, res, body) => {
if (err) throw new Error(err);
if (res && res.statusCode == 200) {
console.log('Success');
} else {
console.log('Error');
};
});
const form = req.form();
form.append('file', fs.createReadStream('./location/to/file'));

Download a youtube video file in node js using ytdl

I want to make user able to download a youtube video using node-ytdl.
For example when client side make a GET request for certain route the video should be downloaded in response.
var ytdl = require('ytdl-core');
var express= require('express');
//Init App Instance
var app=express();
app.get('/video',function(req,res){
var ytstream=ytdl("https://www.youtube.com/watch?v=hgvuvdyzYFc");
ytstream.on('data',function(data){
res.write(data);
})
ytstream.on('end',function(data){
res.send();
})
})
Above is my nodejs code. Even though in network it seems to download the response it does not make user download as a file.I don't want to store any file on server.It would be great if someone could help me how to solve the issue.
res object is a writable stream so you can directly pipe the output of ytdl to res object like this -
ytdl("http://www.youtube.com/watch?v=xzjxhskd")
.on("response", response => {
// If you want to set size of file in header
res.setHeader("content-length", response.headers["content-length"]);
})
.pipe(res);
You have to also pass the headers. Try it:
app.get('/video', (req, res) => {
var url = "https://www.youtube.com/watch?v=hgvuvdyzYFc";
res.header("Content-Disposition", 'attachment; filename="Video.mp4');
ytdl(url, {format: 'mp4'}).pipe(res);
});
If someone is still getting an error just update the package to latest version by running:
npm i ytdl-core#latest
Ok, so make a string var, then add data to it on the data event. On end, send everything. Here is an example:
const ytdl = require("ytdl-core"),
app = require("express")();
app.get("/video", (req, res) => {
let data = "", vid = ytdl("https://www.youtube.com/watch?v=hgvuvdyzYFc");
vid.on("data", d => data += d);
vid.on("end", () => res.send(data));
res.header("Content-Disposition", 'attachment; filename="Video.mp4');
});

Resources