I have a file stored on an external server. I want to be able to call GET request to my own NodeJS server (using express). What I'm currently doing is almost OK, but it does not trigger browser to download the file (no browser UI for the download is shown):
const express = require('express');
const app = express();
app.get('/download-file', (req, res) => {
const externalRequest = http.request({
hostname: 'my.external-server.com',
path: '/my/path/my-file.zip',
}, (externalRes) => {
res.setHeader('Content-Disposition', 'attachment; filename="MyFile.zip"');
externalRes.pipe(res);
});
return externalRequest.end();
});
app.listen(8080, () => console.log('Server is listening'));
What am I missing here? I see that triggering a GET request to localhost:8080/download-file is actually fetching it, but no UI for download is shown.
This is the code that is running in one of my pet projects, hope it helps.
It pipes the download request ok, but there is no size info for the download, so it becames one of that downloads that you dont know when will finish.
const http = require('http')
app.get('/down_file/:file_name', (req, res) => {
const fileName = req.params.file_name
const url = "http://externalUrl/" + fileName
var externalReq = http.request(url, function(externalRes) {
res.setHeader("content-disposition", "attachment; filename=" + fileName);
externalRes.pipe(res);
});
externalReq.end();
})
Related
I'm want to upload big file to my localhost server. And because the file size will be big ( 500MB maybe ), so I need to send the data chunk by chunk from client. Then my Nodejs server will keep appending the data to a temp file. Finally, I will change the file format and save it.
The problem is, I don't know how to send & read data properly. This is how I'm doing now, in my server I keep getting {} object.
Client Side:
// Prepare & Start Upload
const reader = new FileReader();
reader.addEventListener("load", async () => {
await fetch('/api/v1/file/upload/', {
method: 'POST',
body: reader.result
});
})
reader.readAsArrayBuffer( file.slice(0) ); // try to read whole file(small) first
My app setup:
/* Register Middlewares */
app.use(express.json())
app.use(express.urlencoded({extended:true}))
app.use('/api/v1/file/upload', fileUploadRouter)
app.use(express.static('./views'))
app.use(appError)
/* App Start */
const PORT = process.env.PORT || 3000
app.listen(PORT, () => console.log('Listening to: localhost:'+PORT))
My route
fileUploadRouter.post('/', async ( req, res, next ) => {
var buffer = req.body
console.log(buffer)
})
Thank for your help!
I have a very basic question about a node application, and a question about HTTP requests. It's the first time I create a node app with server, and I just can't seem to get the different components to work together.
This is my server.js
var express = require('express');
var multer = require('multer');
const request = require('request');
const upload = multer({dest: __dirname + '/uploads/images'});
const app = express();
const PORT = 3000;
app.use(express.static('public'));
app.post('/upload', upload.single('photo'), (req, res) => {
if(req.file) {
res.json(req.file);
}
else throw 'error';
});
app.listen(PORT, () => {
console.log('Listening at ' + PORT );
});
Then I have a file app.js with a motion-detection system. Every time motion is detected, a picture is taken. This all works fine.
Then the picture should be sent to the server. This is what I can't figure out.
I created a function toServer() that should post the detected data to the server
const request = require('request');
function toServer(data) {
const formData = {
// Pass data via Buffers
my_buffer: data,
// Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS}
// Use case: for some types of streams, you'll need to provide "file"-related information manually.
// See the `form-data` README for more information about options: https://github.com/form-data/form-data
};
request.post({url:'http://localhost:3000/upload', formData: formData}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('Upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
};
Problem 1: when running the server.js on localhost:3000, it doesn't find any of the scripts loaded in index.html nor my app.js.
Problem 2: when running the index.html on live-server, all scripts are found, but i get the error "request is not defined".
I am pretty sure there is some basic node setup thing I'm missing.
The solution for toServer() might be more complicated.
Thanks for your time,
Mustard Shaper
Problem 1:
this could happen because you have not specified to render your index.html.
for example:
res.render('index')
if it's not because of the single quotes in upload.single('photo') try double quotes.
Another possible error could be that you are missing a default display engine setting.
an example: https://www.npmjs.com/package/hbs
Problem 2:
it may be because you are missing the header
var request = require('request');
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: 'http://localhost',
body: "example"
}, function(error, response, body){
console.log(body);
});
See more at https://expressjs.com/
I have a react app in which I have a button. Basically a div.
This is returned from my Button Component and everything else are props.
<button className={"button "+styleButton} onClick={handleClick}>
{source && <img src={source} alt={alt} className={"image "+styleImage} /> }
<h3 className="text">{children}</h3>
</button>
Now what I did when someone clicks this Button(div) is :
const handleClick = () => {
console.log('downloading...');
let a = document.createElement('a');
a.href = '192.168.43.102/download/brief';
a.download = 'brief.pdf';
a.click();
}
On clicking on that div, I want a pdf to be downloaded on the client side. There are hundreds to ways on the internet. Some send a request with(axios) and download on front-end and then create a downloadable link and some just use an anchor tag.
I tried some of these but I can't make it working. Also on the express side.
This route is my express side:
const router = require('express').Router();
const { Router } = require('express');
const path = require('path');
const { route } = require('./api');
const brief = path.join(__dirname, '..', '/public/resources/krishi-brief.pdf');
const uml = path.join(__dirname, '..', '/public/resources/krishi-uml.pdf');
router.get('/brief', (req, res) => {
res.sendFile(brief);
});
router.get('/uml', (req, res) => {
res.download(uml);
});
router.get('/proposal', (req, res) => {
res.send("Not found");
});
router.get('/ppt', (req, res) => {
res.send("Not found");
});
module.exports = router;
I have a very good pfd which is non-corrupted but when I get the file, it is corrupted because none of the applications can open it.
I also tried:
router.get('/uml', (req, res) => {
res.set({
'Content-Type': 'application/pdf'
})
res.download(uml);
});
But now I am confused about the implementation and also if this is the right way.
Please tell me if this is the right(professional) way to do this in react app and where is it wrong? I am only getting corrupted file :(
OK so when I click on the download, the server 192.168.43.102 should be written as http://192.168.43.102 and the anchor tag won't give or throw and error but just download something which I am not sure about which is not even on your route.
Basic thing I was struggling on.
SOLVED THANKS TO #Patrick Evans
I am creating my own web project and i need some help.
At the website, the client is requested to upload a face photo.
Then , when the client presses "upload" button , his photo is sent with a request to "face++" api which gives back details about the photo such as emotions and gender, at a different ejs page. At the new page the client sees his photo and below are the details about his photo.
It works fine , but when the client gets back to the homepage, and chooses a different new photo, then presses upload , he sees his new photo that he chose, but gets the same details as were at the last photo (details from face++ api).
I use the following:
express.
unirest for making the request to "face++" api.
cloudinary for having a url, and using the url at the face++ request(the url represents the client's photo).
multer for storing at local drive.
When i print out the details which return from "face++" api , at the "requestFromApi.end()" function , i already notice the details havent changed from prior request, but i do notice at cloudinary that a different photo was uploaded.
I attached my app.js code.
Thanks alot for any help :)
var unirest = require("unirest");
var requestFromApi = unirest("POST", "https://faceplusplus-
faceplusplus.p.rapidapi.com/facepp/v3/detect");
var cloudinary = require("cloudinary").v2;
const express = require('express');
const multer = require('multer');
const app = express();
const path = require("path");
var bodyParser = require("body-parser")
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
limit: '50mb',
extended: true
}));
app.set("view engine", "ejs");
cloudinary.config({
cloud_name: 'dkqvnprcj',
api_key: '756886954695832',
api_secret: 'you know i cant give you that...'
});
app.get("/", function (req, res) {
res.render("FaceApp.ejs");
});
// SET STORAGE
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() +
path.extname(file.originalname));
}
})
var upload = multer({ storage: storage })
app.post('/upload', upload.single('photo'), (req, res) => {
if (req.file) {
cloudinary.uploader.upload(req.file.path, function (error, result) {
//console.log(req.file);
let result_ = result;
let url = result.url;
//console.log(url)
requestFromApi.query({
return_attributes: "gender,age,smiling,facequality,eyestatus,emotion,ethnicity,beauty,skinstatus",
image_url: url
});
requestFromApi.headers({
"x-rapidapi-host": "faceplusplus-faceplusplus.p.rapidapi.com",
"x-rapidapi-key": "9dd7fa4266mshf1c29ba307ecf2dp1bb1dajsna431d00b6273",
"content-type": "application/x-www-form-urlencoded"
});
requestFromApi.form({});
requestFromApi.end(function (result) {
if (result.error) throw new Error(result.error);
else {
let detailsFromApi = JSON.parse(JSON.stringify(result.body.faces));
detailsFromApi.forEach(function (element) {
console.log(element);
});
res.render("image",{result_ : result_, detailsFromApi:detailsFromApi});
}
});
});
}
else throw 'error';
});
SOLVED THANKS TO #Patrick Evans [1]: https://stackoverflow.com/users/560593/patrick-evans
I had to make sure i call "Unirest" at every single Post request, and not just at the beginning of the execution.
My uploaded form has a file and a field "filepath" which is dynamically generated and contains the desired filepath of the file I'm uploading.
Example:
filepath: "assets/images/asset-01-02/"
I'm trying to set this field as a variable so I can save the file to this directory to keep uploaded files organized.
Current code:
const cors = require('cors');
const express = require('express');
const app = express();
const formidable = require('formidable');
app.use(cors());
app.options('*', cors());
app.post('/upload', (req, res) => {
var form = new formidable.IncomingForm();
form.parse(req, (err, fields, files) => {
if (err) {
console.log('Error', err)
throw err
}
console.log(fields.filepath); //Output e.g. "assets/images/asset-01-02/"
})
form.on('fileBegin', (name, file) => {
//Need to use fields.filepath after '/public/uploads/'
//e.g. __dirname + '/public/uploads/' + fields.filepath + file.name;
file.path = __dirname + '/public/uploads/' + file.name;
});
form.on('file', (name, file) => {
console.log('Uploaded ' + file.name);
});
});
app.listen(80, function(){
console.log('Listening on Port 80...');
});
I need to get the fields.filepath value passed to the form.on('fileBegin') function but I'm not sure how to. I haven't come across any examples of this specific issue.
As far as I am understanding your question, you are trying to send 'filepath' with 'multipart/form-data' or from client to server with uploaded files.
and you are trying to catch and set this 'filepath' using form.parse 'fields' into form.parse callback.
your code do not work simply because form.on('fileBegin') callback will execute before form.parse callback.
here is execution order for callback in Formidable.(can change due to asynchronous functions)
form.on('fileBegin')
form.on('file')
form.parse()
form.on('end')
instead passing 'filepath' with 'form-data', send it with query like localhost/upload?filepath=assets/images/asset-01-02
and get it like
var filepath = req.query.filepath;
in your code