I have a problem uploading an jpg file with node.js to my tomcat server - somewhere in the upload the file content is changed. I think, it is something with the encoding, but I hav no idea what I'm missing.
The node.js code is:
var agentOptions;
var agent;
agentOptions = {
host: 'this.is.my.server'
, port: '8443'
, path: '/'
, rejectUnauthorized: false
};
agent = new https.Agent(agentOptions);
var binaryFilename = "image.jpg";
var fContent = fs.readFileSync( binaryFilename );
console.log( "file size = " + fContent.length );
var boundary = '69b2c2b9c464731d'
var content = "--"+boundary+"\r\n"
+ "Content-Disposition: form-data; name=\"file\"; filename=\"image.jpg\"\r\n"
+ "Content-Type: application/octet-stream\r\n"
+ "Content-Transfer-Encoding: BINARY\r\n"
+ "\r\n"
+ fContent + "\r\n"
+ "--"+boundary+"--\r\n"
postOptions = {
headers: {
'Content-Type': 'multipart/form-data; boundary='+boundary ,
'Content-Length': Buffer.byteLength(content) ,
'Authorization': 'Basic ABCEDFE..'
} ,
host: 'this.is.my.server' ,
port: '8443' ,
path: '/restservices/uploadimage?data=value&data2=value2' ,
method: 'POST' ,
strictSSL: false ,
agent: agent
} ;
// Set up the request
post_req = https.request(
postOptions,
function(res) {
//
res.setEncoding('utf8') ;
res.on('data', function (chunk) {
console.log('Response: ' + chunk) ;
}) ;
}) ;
// post the data
post_req.write(content) ;
post_req.end() ;
Java code on the server starts with
#RequestMapping(value = "/uploadimage", method = RequestMethod.POST )
public #ResponseBody String uploadpreview(#RequestParam String data, #RequestParam String data1, #RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
....
Start of the image before upload:
Start of the image after upload:
(source: dataplan.de)
Every byte with the highest bit set is converted to three bytes EF BF BD
I tried several things, maybe I'm missing something simple - at the moment I have no idea what I'm doing wrong.
Thanks for any ideas and tipps
Klaus
Here's another attempt:
const https = require('https');
const formData = require('form-data')();
var binaryFilename = process.argv[2] || 'image.jpg';
let request = https.request({
host: 'this.is.my.server'
port: '8443',
path: '/',
method: 'POST',
headers: formData.getHeaders()
}, (res) => {
res.on('data', (data) => {
console.log('Data received: ', data.toString());
});
});
request.on("error", (e) => {
console.error(e);
});
formData.append('image_file', require("fs").createReadStream(binaryFilename));
formData.pipe(request);
Related
I'm making a HTTP request to a password protected site using the request module in npm, putting in a password, storing a cookie, then making the request once the cookie is stored and verified. I am able to get the same headers as I would on a normal browser request, but hte body itself, instead of being the HTML document I get in a browser, just looks like this:
� �Z�r�H��c��䞙��pT���Ī$3�ƾ�~Y�#�MK8���>*��?�z)�?U���ݨ�J�혳��섯tB��x��c��?�����������0�H�����V��O'�7����}���L�"˖}/ta�xn�g#�ݱ�O�����
Any ideas what might be causing this or how I can fix it?
In addition, when I run this from the command prompt, the computer "dings"
Here is the full node.js code I am running (minus the URLs/passwords/etc.)
var parsedurl1 = url.parse( urlstring1 );
var options1 = {
hostname: parsedurl1.hostname,
port: ( parsedurl1.port || 80 ), // 80 by default
method: 'POST',
path: parsedurl1.path,
headers: {
'Host': hostname
,'User-Agent': myuseragent
,'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
,'Accept-Language':"en-US,en;q=0.5"
,'Accept-Encoding': "gzip, deflate"
,'Referer': hostname
,'Content-Type': "text/html; charset=utf-8"
,'Content-Length': Buffer.byteLength(postData)
,'Connection': "keep-alive"
,'Upgrade-Insecure-Requests': "1"},
};
var cookiefile ;
var postData=querystring.stringify({
'email': myemail
,'password':mypassword
,'action': 'login'
,'go.x': 0
,'go.y': 0
})
var cookiefile;
var callback = function ( response ) {
// display returned cookies in header
var setcookie = response.headers["set-cookie"];
if ( setcookie ) {
setcookie.forEach(
function ( cookiestr ) {
cookiefile = cookiestr;
fs.writeFile(cookiefilelocation, cookiestr);
console.log( "COOKIE:" + cookiestr );
}
);
}
var data = "";
response.on(
"data",
function ( chunk ) { data += chunk; }
);
response.on(
"end",
function () {
newcookiefile = cookiefile.substr(0, cookiefile.indexOf(";"));
var parsedurl2 = url.parse( urlstring2 );
var options2 = {
url: urlstring2,
// port: ( parsedurl2.port || 80 ), // 80 by default
method: 'GET',
// path: parsedurl2.path,
headers: {
"Host": hostname
,"User-Agent": myuseragent
,'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
,'Accept-Language':"en-US,en;q=0.5"
,'Accept-Encoding': "gzip, deflate"
,'Referer':hostname
,'Cookie': newcookiefile
,'Connection': "keep-alive"
,'Upgrade-Insecure-Requests': "1"},
};
function callback3(error, response, body){
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response.headers ); // Print the response status code if a response was received
console.log('body:', body.substr(1,1000));
fs.writeFile('./config/pullfiles/mostrecent.txt', body);
}
requestlib(options2, callback3);
}
);
};
var request = http.request(options1, callback);
request.on(
"error",
function( err ) {
console.error( "RERROR:" + err );
}
);
request.write(postData);
request.end(); // let request know it is finished sending
I figured it out! This gibberish was caused by my lack of the 'gzip: true' option is my request(). Now the second request reads:
url: urlstring2
,gzip: true
,headers:{...
Why does requestify.request() crash because it doesn't think it was given the method POST
var postBody = querystring.stringify(dat);
var postOptions = {
host: 'https://www.example.com'
, path: '/admin'
, method: 'post' // POST, 'POST', post
, headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postBody) }
};
var postReq = requestify.request(postOptions, function (err, resp, respBody) {
resp.setEncoding('utf8');
resp.on('data', function (chunk) {
console.log('Response: ' + chunk);
});
});
It looks like you are using an old version of the documentation for the newer version of requestify
Read the API reference section of https://github.com/ranm8/requestify
And read just a little lower down it see a requestify.request() example.
Options doesn't have host, path, ...
I am trying to automatically post some assets on a Github release I programmatically create.
Here is my upload function:
function uploadFile(fileName, uploadUrl, callback){
var uploadEndPoint = url.parse(uploadUrl.substring(0,uploadUrl.indexOf('{')));
options.host = uploadEndPoint.hostname;
options.path = uploadEndPoint.pathname+'?name=' + fileName;
options.method = 'POST';
options.headers['content-type'] = 'application/zip';
var uploadRequest = https.request(options, callback);
uploadRequest.on('error', function(e) {
console.log('release.js - problem with uploadRequest request: ' + e.message);
});
var readStream = fs.ReadStream(path.resolve(__dirname,'builds',fileName));
readStream.pipe(uploadRequest);
readStream.on('close', function () {
req.end();
console.log('release.js - ' + fileName + ' sent to the server');
});
}
At the end of this I get a 404 not found
I tried auth from token and user/password
I checked the url
I though it might be because of SNI, but I don't know how to check that.
Any clue ? Thanks !
I found a solution to that problem by NOT using the low level node.js modules and using instead restler which is a library that handles SNI.
Here is how is used it:
rest = require('restler'),
path = require('path'),
fs = require('fs');
fs.stat(path.resolve(__dirname,'builds',fileName), function(err, stats){
rest.post(uploadEndPoint.href+'?name=' + fileName, {
multipart: true,
username: GITHUB_OAUTH_TOKEN,
password: '',
data: rest.file(path.resolve(__dirname,'builds',fileName), null, stats.size, null, 'application/zip')
}).on('complete', callback);
});
Hope that will help someone :)
EDIT on 27/02/2015: We recently switched from restler to request.
var
request = require('request'),
fs = require('fs');
var stats = fs.statSync(filePath);
var options = {
url: upload_url.replace('{?name}', ''),
port: 443,
auth: {
pass: 'x-oauth-basic',
user: GITHUB_OAUTH_TOKEN
},
json:true,
headers: {
'User-Agent': 'Release-Agent',
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/zip',
'Content-Length': stats.size
},
qs: {
name: assetName
}
};
// Better as a stream
fs.createReadStream(filePath).pipe(request.post(options, function(err, res){
// Do whatever you will like with the result
}));
The upload_uri can be retrieved through a get request on an existing release or in the response directly after the release creation.
I'm trying to post images to Twitter using the Oauth module. Here is what I have:
It throws a 403 error, I know im doing something wrong with how I add the media to the post but Im just not sure where to go from here.
var https = require('https');
var OAuth= require('oauth').OAuth;
var keys = require('./twitterkeys');
var twitterer = new OAuth(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
keys.consumerKey,
keys.consumerSecret,
"1.0",
null,
"HMAC-SHA1"
);
var params = {
status : "Tiger!",
media : [("data:" + mimeType + ";base64,") + fs.readFileSync(path,'base64')]
};
//function(url, oauth_token, oauth_token_secret, post_body, post_content_type, callback)
twitterer.post("https://upload.twitter.com/1/statuses/update_with_media.json",
keys.token, keys.secret, params, "multipart/form-data",
function (error, data, response2) {
if(error){
console.log('Error: Something is wrong.\n'+JSON.stringify(error)+'\n');
}else{
console.log('Twitter status updated.\n');
console.log(response2+'\n');
}
});
Here is what I belive im supose to be doing but I don't know how to do that in the Node.js Oauth module.
Posting image to twitter using Twitter+OAuth
Reviewing the code, it looks like there's no multipart/form-data handling at all in the node-oauth package right now. You can still use the node-oauth function to create the authorization header, but you'll have to do the multipart stuff on your own.
There are probably third-party libraries that can help out with that, but here's how I got it to work constructed by hand.
var data = fs.readFileSync(fileName);
var oauth = new OAuth(
'https://api.twitter.com/oauth/request_token',
'https://api.twitter.com/oauth/access_token',
twitterKey, twitterSecret,
'1.0', null, 'HMAC-SHA1');
var crlf = "\r\n";
var boundary = '---------------------------10102754414578508781458777923';
var separator = '--' + boundary;
var footer = crlf + separator + '--' + crlf;
var fileHeader = 'Content-Disposition: file; name="media"; filename="' + photoName + '"';
var contents = separator + crlf
+ 'Content-Disposition: form-data; name="status"' + crlf
+ crlf
+ tweet + crlf
+ separator + crlf
+ fileHeader + crlf
+ 'Content-Type: image/jpeg' + crlf
+ crlf;
var multipartBody = Buffer.concat([
new Buffer(contents),
data,
new Buffer(footer)]);
var hostname = 'upload.twitter.com';
var authorization = oauth.authHeader(
'https://upload.twitter.com/1/statuses/update_with_media.json',
accessToken, tokenSecret, 'POST');
var headers = {
'Authorization': authorization,
'Content-Type': 'multipart/form-data; boundary=' + boundary,
'Host': hostname,
'Content-Length': multipartBody.length,
'Connection': 'Keep-Alive'
};
var options = {
host: hostname,
port: 443,
path: '/1/statuses/update_with_media.json',
method: 'POST',
headers: headers
};
var request = https.request(options);
request.write(multipartBody);
request.end();
request.on('error', function (err) {
console.log('Error: Something is wrong.\n'+JSON.stringify(err)+'\n');
});
request.on('response', function (response) {
response.setEncoding('utf8');
response.on('data', function (chunk) {
console.log(chunk.toString());
});
response.on('end', function () {
console.log(response.statusCode +'\n');
});
});
first question here, so apologies if it turns out to be something very obvious
I am trying to call the paypal adaptive payments api via node.js and am getting a 580001 invalid request error. I can make a successfull call via curl with the below message and headers, but not through node.
any help would be much appreciated.
var API_endpoint = "svcs.sandbox.paypal.com";
var API_user = '';
var API_pass = '';
var API_sig = '';
message='requestEnvelope.errorLanguage=en_US&actionType=PAY&senderEmail=test_1320882990_per#gmail.com&receiverList.receiver(0).email=test2_1320887729_biz#gmail.com& receiverList.receiver(0).amount=100.00¤cyCode=USD&cancelUrl=http://your_cancel_url& returnUrl=http://your_return_url'
//var params = qs.parse(message);
//params = qs.stringify(params);
var req_options = {
host: API_endpoint,
method: 'POST',
path: '/AdaptivePayments/Pay',
headers: {
'Host': API_endpoint,
'Content-Type': 'application/x-www-form-urlencoded',
//'Content-Type': 'text/namevalue',
'Content-Length': message.length,
'X-PAYPAL-REQUEST-DATA-FORMAT:':'NV',
'X-PAYPAL-RESPONSE-DATA-FORMAT':'NV',
'X-PAYPAL-SECURITY-USERID':API_user,
'X-PAYPAL-SECURITY-PASSWORD':API_pass,
'X-PAYPAL-SECURITY-SIGNATURE':API_sig,
'X-PAYPAL-APPLICATION-ID':'APP-80W284485P519543T'
}
}
fs.readFile('/home/dev/.ssh/sandbox-paypal-private.pem', 'ascii', function(err, key){
fs.readFile('/home/dev/.ssh/sandbox-paypal-public.pem', 'ascii', function(err, cert){
req_options.key=key
req_options.cert=cert
var req = https.request(req_options, function(res){
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.on('data', function(d){
var response = d.toString();
console.log(response)
});
});
req.write(message);
req.end();
req.on('error', function request_error(e) {
console.log(e);
});
});
});
I'm not sure if it's only a copy paste problem, but your message variable does not seem to contain properly formatted string. It has white spaces and the special characters are not encoded.
requestEnvelope.errorLanguage=en_US&actionType=PAY&senderEmail=test_1320882990_per#gmail.com&receiverList.receiver(0).email=test2_1320887729_biz#gmail.com&receiverList.receiver(0).amount=100.00¤cyCode=USD&cancelUrl=http://your_cancel_url& returnUrl=http://your_return_url'.
It should look like this:
requestEnvelope.errorLanguage=en_US&actionType=PAY&senderEmail=test_1320882990_per%40gmail.com&receiverList.receiver(0).email=test2_1320887729_biz%40gmail.com& receiverList.receiver(0).amount=100.00¤cyCode=USD&cancelUrl=http%3A%2F%2Fyour_cancel_url&returnUrl=http%3A%2F%2Fyour_return_url
There's a trailing colon in one of your header fields; Rather than:
'X-PAYPAL-REQUEST-DATA-FORMAT:'
You should have:
'X-PAYPAL-REQUEST-DATA-FORMAT'