Request is easy to use, however, I encountered a strange problem:
TypeError: The header content contains invalid characters
This is my code(very simple, just a GET request):
let request = require('request');
let url = "https://www.baidu.com/s?wd=整天就是背背背记记记,或者有些正,时间就这么浪费了";
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
} else {
console.log(error);
}
});
when I ran the code, the error occured. I hadn't set any headers in my request.
Request doesn't support the chinese characters? I am confused, anyone advice??
Since you are using a GET request, your URL path and parameters are members of the request headers. You should encode the parameter values like this:
let url = "https://www.baidu.com/s?wd=" +
encodeURIComponent("整天就是背背背记记记,或者有些正,时间就这么浪费了");
This will create an URL containing only ASCII characters:
https://www.baidu.com/s?wd=%E6%95%B4%E5%A4%A9%E5%B0%B1%E6%98%AF%E8%83%8C%E8%83%8C%E8%83%8C%E8%AE%B0%E8%AE%B0%E8%AE%B0%EF%BC%8C%E6%88%96%E8%80%85%E6%9C%89%E4%BA%9B%E6%AD%A3%EF%BC%8C%E6%97%B6%E9%97%B4%E5%B0%B1%E8%BF%99%E4%B9%88%E6%B5%AA%E8%B4%B9%E4%BA%86
I need to get a file from a URL (any file type) and base64 encode it, and then send it to an API that only accepts base64 encoded files.
Here is the documentation description just for clarification:
The file must be base64-encoded. You should not use MIME style
encoding with newline characters at a maximum line length of 76.
Instead, you are required to omit these newlines. (If you don’t omit
the newlines, the stored file won’t be usable.)
Below is the current code I am using. I am able to upload the file to the API in question, but the file has been corrupted for some reason. The current URL I am using for this is (just a dummy image for testing):
dummy image
I am getting the file to upload to the API in question - but when opened it is corrupted. I am assuming it has something to do with the base64 restrictions noted above for the API. My code for the base64 encoding.
UPDATED - async accounted for and still the same issue:
const request = require('request');
function sendBase64EncodedFile( url ) {
request.get( url , function (error, response, body) {
if (!error && response.statusCode == 200) {
var data = new Buffer(body).toString('base64');
/*
Create xml to send to API
*/
var xml = '<qdbapi><usertoken>hidden for privacy issues</usertoken><apptoken>hidden for privacy issues</apptoken><field fid="8">Some testing body text</field><field fid="9" filename="someFileName.png">' + data + '</field></qdbapi>';
var qb_url = "hidden for privacy issues";
request({
url: qb_url,
method: "POST",
'headers': {
'Content-Type': 'application/xml',
'QB-ACTION': 'API_AddRecord'
},
body: xml
}, function (error2, response2, body2){
});
} else {
//console.log( body );
}
});
}
I have a problem with PNG image ganeration at server side, using Fabric.js + Node.js. I am wondering that there is no one with similar probem found in forums. I am in total despair. It makes under risk of using Fabric.js in our project.
PNG image generation in Fabric.js Node.js service fails on a unregular basis. I can not determine why sometimes it gets generated and sometimes not.
I need to generate PNG at server side. I’ve developed a small Node.js webservice based on samples here and here.
I’ve developed also a custom Fabric.js image class “RemoteImage”, based on Kangax sample here.
To minimize JSON string size, I am storing a dataless JSON in my database and images are supposed to be loaded using provide link in “src” attribute of the Fabric.js Image element. As the result, I need to load following JSON into canvas that contains 3 images:
{"objects":[{"type":"remote-image","originX":"left","originY":"top","left":44,"top":29,"width":976,"height":544,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":0.5,"scaleY":0.5,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","localId":"222c0a8b-46ac-4c01-9c5c-79753937bc24","layerName":"productCanvas","itemName":"mainCanvas","src":"http://localhost:41075/en/RemoteStorage/GetRemoteItemImage/222c0a8b-46ac-4c01-9c5c-79753937bc24","filters":[],"crossOrigin":"use-credentials","alignX":"none","alignY":"none","meetOrSlice":"meet","remoteSrc":"http://localhost:41075/en/RemoteStorage/GetRemoteItemImage/222c0a8b-46ac-4c01-9c5c-79753937bc24","lockUniScaling":true},
{"type":"remote-image","originX":"left","originY":"top","left":382.5,"top":152.25,"width":292,"height":291,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":0.43,"scaleY":0.43,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","localId":"8d97050e-eae8-4e95-b50b-f934f0df2d4c","itemName":"BestDeal.png","src":"http://localhost:41075/en/RemoteStorage/GetRemoteItemImage/8d97050e-eae8-4e95-b50b-f934f0df2d4c","filters":[],"crossOrigin":"use-credentials","alignX":"none","alignY":"none","meetOrSlice":"meet","remoteSrc":"http://localhost:41075/en/RemoteStorage/GetRemoteItemImage/8d97050e-eae8-4e95-b50b-f934f0df2d4c","lockUniScaling":true},
{"type":"remote-image","originX":"left","originY":"top","left":38,"top":38.5,"width":678,"height":370,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":0.21,"scaleY":0.21,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","localId":"42dc0e49-e45f-4aa7-80cf-72d362deebb7","itemName":"simple_car.png","src":"http://localhost:41075/en/RemoteStorage/GetRemoteItemImage/42dc0e49-e45f-4aa7-80cf-72d362deebb7","filters":[],"crossOrigin":"use-credentials","alignX":"none","alignY":"none","meetOrSlice":"meet","remoteSrc":"http://localhost:41075/en/RemoteStorage/GetRemoteItemImage/42dc0e49-e45f-4aa7-80cf-72d362deebb7","lockUniScaling":true}],"background":""}
At Node.js server side I use the following code. I am transferring JSON string in base64 encoding to avoid some special-character problems:
var fabric = require('fabric').fabric;
function generatePNG(response, postData) {
var canvas = fabric.createCanvasForNode(1500, 800);
var decodedData = new Buffer(postData, 'base64').toString('utf8');
response.writeHead(200, "OK", { 'Content-Type': 'image/png' });
console.log("decodedData data: " + JSON.stringify(decodedData));
console.log("prepare to load");
canvas.loadFromJSON(decodedData, function () {
console.log("loaded");
canvas.renderAll();
console.log("rendered");
var stream = canvas.createPNGStream();
stream.on('data', function (chunk) {
response.write(chunk);
});
stream.on('end', function () {
response.end();
});
});
}
In a console I see that message “prepare to load” appears, but message “loaded” does not. I am not an expert in Node.js and this is the only way how I can determine that error happens during the loadFromJSON call. But I do not understand, where is the problem.
I am using fabric v.1.5.0 and node-canvas v.1.1.6 on server side.
Node.js + Fabric.js service is running on Windows 8 machine. And I am makeing a request from .NET MVC application, using POST request.
Remark: May be I needed to omit my comment about base64 encoding as it is confusing. I tried to run with normal json string and the same result.
If the images referenced in the JSON are on the NodeJS server, try changing the file path to the directory path on the server as opposed to a web URL.
I'm not sure I fully understand how you are using the base64 image, but there are some character corrections that are required for base64 images. I of course don't recall the specifics and don't have my code handy that I perform this in, but a Google search should set you in the right direction.
I hope those ideas help.
It turned out that problem was related to the way how fabric.util.loadImage method works. For external images loadImage mathod makes an http request assuming that no error can happen. Method used for requesting external images just simply logs an error and ends, instead of returning error through callback method back to loadImage method. At this moment image loading routine falls apart with erroneous state and without any feedback - it just terminates crashing whole Node.js.
It took 3 days for me to finally find out that actually it was my image supplying webservice who just responds with status code 500 making Node.js request to fail. Using my image supplying webservice through browser worked correctly and therefore at the first moment I did not considered that error is related particularly with request.
As the result I rewrote fromObject method of my custom Fabric.js object. Now it works in more safe fashion and in case of error I can get more feedback. Here is the implementation of my fromObject method. For http request I use module "request".
fabric.RemoteImage.fromObject = function (object, callback) {
var requestUrl = object.remoteSrc;
request({
url: object.remoteSrc,
encoding: null
},
function(error, response, body) {
if (error || response.statusCode !== 200) {
var errorMessage = "Error retrieving image " + requestUrl;
errorMessage += "\nResponse for a new image returned status code " + response.statusCode;
if (error) {
errorMessage += " " + error.name + " with message: \n" + error.message;
console.log(error.stack);
}
console.log(errorMessage);
callback && callback(null, new Error(errorMessage));
} else {
var img = new Image();
var buff = new Buffer(body, 'binary');
img.src = buff;
var fabrImg = new fabric.RemoteImage(img, object);
callback && callback(fabrImg);
}
});
};
I'm using Node.js to download images from a server and save them. Occasionally I get served corrupted images that in-turn break some video rendering in another part of my program. I'd like to validate these images before they're saved.
Right now I have a function that looks like this:
function saveImage(res, destination, imageName, url) {
var imgName = './' + destination + '/' + imageName + '.jpg';
var type = res.headers['content-type'];
if (type === 'image/jpg' || type === 'image/jpeg') {
res.pipe(fs.createWriteStream(imgName));
} else {
console.log('corrupt Image caught: ', url,' headers: ',type);
}
}
You'll see that I'm already checking the content type. This actually doesn't stop some of the bad images. They appear to have the correct headers, but are saved as 0 KB files.
Is there an easy way to check the file size of the image that isn't reliant on the content-length? Fron my understanding that isn't always set.
I'm experimenting with Node.js and web scraping. In this case, I'm trying to scrape the most recent songs from a local radio station for display. With this particular website, body returns nothing. When I try using google or any other website, body has a value.
Is this a feature of the website I'm trying to scrape?
Here's my code:
var request = require('request');
var url = "http://www.radiomilwaukee.org";
request(url, function(err,resp,body) {
if (!err && resp.statusCode == 200) {
console.log(body);
}
else
{
console.log(err);
}
});
That's weird, the website you're requesting doesn't seem to return anything unless the accept-encoding header is set to gzip. With that in mind, using this gist will work: https://gist.github.com/nickfishman/5515364
I ran the code within that gist, replacing the URL with "http://www.radiomilwaukee.org" and see the content within the sample.html file once the code has completed.
If you'd rather have access to the web page's content within the code, you could do something like this:
// ...
req.on('response', function(res) {
var body, encoding, unzipped;
if (res.statusCode !== 200) throw new Error('Status not 200');
encoding = res.headers['content-encoding'];
if (encoding == 'gzip') {
unzipped = res.pipe(zlib.createGunzip());
unzipped.on("readable", function() {
// collect the content in the body variable
body += unzipped.read().toString();
});
}
// ...