something about request(url).pipe() - node.js

when I use request(url).pip(fs.createWriteStream("1.jpg")), url include some special codes just as "#" and "×", then the NODE.js cannot create the jpg picture, and if I create the http file service, use the url without the special code, I can get the jpg picture correctly. can somebody tell me how to handle these special codes in url?
thank you very much!

You should provide the code but I've tried this code for you.
const fs = require('fs')
const http = require('http')
const request = require('request')
let url = 'https://upload.wikimedia.org/wikipedia/en/8/8a/Text_placeholder_image.jpg' // some jpg
request(url).pipe(fs.createWriteStream('1.jpg'))
http.createServer((req, res) => {
fs.readFile('1.jpg', (error, content) => {
if (error) {
// handle error
return
}
res.writeHead(200, 'image/jpeg')
res.end(content, 'utf-8')
})
}).listen(3000)
Then, localhost:3000 worked well.
Used node v6.10.2 and request v2.81.0.

Related

How to make nodejs server act like a proxy and get img from cloudinary then send it to browser

for storage space issues i cannot save images in server so i had to store it in cloudinary
and for seo purposes I had to serve it from my domain not cloudinary's
so i thought to get img files from cloudinary and send it directly to browser (to be served from my domain name )
what i am missing is converting the img file i got from cloudinary api into the right form so i can send it using response object in nodejs
here is the code
app.get('/uploads/img/:imgName', (req, res) => {
axios.get('https://res.cloudinary.com/dkhccaa25/image/upload/blog_img/${req.params.imgName}')
.then(response => {
console.log(response);
/* how to convert response into the right format so it can be sent */
//
//
//
})
.then (response => {
/*converted response */
res.sendFile(response)
})
.catch(error => {
console.log(error);
});
how I can be able to send the file from node server to browser so it can be displayed using
<img src="img url...">
You do not have to use res.sendFile, this will require saving it to the filesystem. Basically - accept the response and pass it directly with the correct content-type header send by the upstream response to the client.
Minimal example:
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/', (req, res) => {
axios.get('https://static.pexels.com/photos/45201/kitty-cat-kitten-pet-45201.jpeg').then((axiosResp) => {
res.header('content-type', axiosResp.headers['content-type']).send(axiosResp.data);
});
});
app.listen(3000);
finally the problem solved by editing on #madflow answer (thanks for him )
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/', (req, res) => {
axios.get('https://static.pexels.com/photos/45201/kitty-cat-kitten-pet-45201.jpeg', {responseType: 'stream'})
.then((axiosResp) => {
res.set({
'Content-Type': axiosResp.headers['content-type']
})
axiosResp.data.pipe(res)
});
});
app.listen(3000);

HTTP GET from node server takes too long

I'm learning node.js currently and I'm stuck with this problem. I was able to successfully create my node.js server and it works when I run it on the terminal. I even console.log the data I am trying to GET and it shows in the terminal but when I try to load it on Postman, it doesn't show anything.
I use localhost:9001/api but it doesn't load. I don't even get any errors.
Here's my code:
const express = require('express');
const app = express();
const fetch = require('node-fetch');
require('dotenv').config();
const api_key = XXXXXXXXXXX
app.use(express.static('public'));
app.listen(9001, () => console.log('listneing at 9001'));
app.get("/api", async (req,res)=> {
console.log("getting data")
const url = `website.com/vi/api/?alt=json&key=${api_key}`
const options={
"method" : "GET"
};
const response = await fetch(url, options)
.then(response => response.json())
.catch(e => {
console.errror({
"message": "oh no",
error : e,
});
});
console.log(response)
});
Not sure how to solve it can anyone please help a new learner? 🙏
Postman needs a response from your side to show Responses.
The console.log() prints the output on your screen but in order to get response in Postman, You have to return a response like
return res.status(response.code).json(response);
This is my way of returning response. You can make your own variable and add values to them.

Downloading a file from a Node.JS API REST (express) with React.JS (Axios Get)

I have a React JS application that as a Backend has an API REST made with Node JS.
Currently, my objective is to be able to download files that are on the server.
The correct behavior should be that the user, after clicking on "Download file", should receive the file (Download with browser).
On the server-side, I have something like this (obviously, I'm gonna simplify it by removing JWT middleware, DB queries, etc..):
const express = require('express');
const router = express.Router();
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
app.use(cors({ origin: "http://localhost:3000" }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
router.get('/download', (req, res, next) => {
res.download("\\\\folder\\subfolder\\myfile.txt");
});
app.use('/api', router);
const PORT = 3001;
app.listen(PORT, function() {
console.log("Server is running on port "+PORT);
});
Then, as I have said, I have a React JS application working as a Frontend:
apihelperdownload () {
return axios.get(API_URL + "download").then(function (response) {
return response;
})
}
.............
function downloadFile() {
apihelperdownload().then(
(res) => {
// Should I do something here with response?
},
(error) => {
}
)
}
<button className="download" onClick={() => downloadFile()}>
Download File
</button>
I have two files on my server, one TXT and one JPG.
Both have the correct path (I'm not getting any "file/path not found" error) and I am receiving a "200 status OK" in both cases... But I can't download the files.
Also:
In the JPG case, in Network Tab, on preview sub-Tab I can see the image (so the browser is receiving the image).
And the response looks like this:
(ignore the params and the different url, it's just that here is not simplified)
- In the TXT case, in Network Tab, on preview sub-Tab I can just see a white page.
And the response looks like this:
As you can see, in this second case (.txt file), the data is "empty" ( "" )
Data is the correct text.. I didn't save the txt file.. So it was empty..
I have checked several related questions like this Download a file from NodeJS Server using Express
But unfortunately, I haven't found how to solve my issue.
1) What am I doing wrong on the server-side?
2) What I have to do with the response on client-side?
Thanks
I have found how to solve it without third-party libraries and in quite an "easy way".
First of all, I have changed the request to POST (since I just made GET because I thought it was the only way).
After that, on the Axios request, we have to indicate the responseType as blob:
function apihelperdownload () {
return axios.post(API_URL + "download",{ key: 'value', headers: authHeader(), responseType: 'blob' }).then(function (response) {
return response;
})
}
Then, when we receive the response, we have to create an URL object as a Blob and a link element to download it.
function downloadFile(filename) {
apihelperdownload().then(
(res) => {
const url = window.URL.createObjectURL(new Blob([res.data]));
const link = document.createElement('a');
link.href = url;
if (typeof window.navigator.msSaveBlob === 'function') {
window.navigator.msSaveBlob(
res.data,
filename
);
} else {
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
}
},
(error) => {
alert("Something went wrong");
}
)
}
With this, we can download almost any kind of file very easily.
You can use js-file-download module.
const FileDownload = require('js-file-download');
Axios.get(API_URL + "download")
.then((response) => {
FileDownload(response.data, 'file.txt');
});
Check this response for more: https://stackoverflow.com/a/41940307/6512445

Node.js Decoding a Base64 Image and saving it via API

I've been trying to get a quick node.js api working, but I'm running into some issues and I was hoping someone could help.
What I'm trying to do: I'm trying to pass a base64 encoded image data URI to my node.js and have it save the file to my server. I believe that I've almost got it working, but for some reason the image is getting corrupted. When I attempt to run the script when I just hardcode the dataURI in, the saved image is perfect. However, when I use the GET request, the saved file is corrupted and I cannot open it.
Here is what I have so far:
const express = require('express');
const fs = require('fs');
const app = express();
app.listen(3000, () => { console.log
('Running on port 3000...');
});
app.get('/api/users', function(req, res) {
let base64String = req.param('datauri');
let base64Image = base64String.split(';base64,').pop();
fs.writeFile('image.png', base64Image, {encoding: 'base64'}, function(err) {
console.log('File created');
});
res.send(base64Image);
});
Any help would be greatly appreciated!
You need to url decode the base64 string to replace the special characters back to their original form. I.E. swap + back to a space
You should be able to use decodeURIComponent()
var base_64 = decodeURIComponent(base_64_string);

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