I'm looking for uploading in node JS a video throught the linkedin API V2 , butI'm still receiving a status code 403. I correctly followed the steps in the documentation. (https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/vector-asset-api#register-an-upload-for-video)
let req = request(`https://assets.mixkit.co/videos/2125/2125-720.mp4`)
.pipe(fs.createWriteStream('video.mp4'));
req.on('close', ()=>{
request({
url: uploadUrl,
method: 'POST',
headers: {
"x-amz-server-side-encryption-aws-kms-key-id": "MY_ID",
"x-amz-server-side-encryption": "aws:kms",
"Content-Type": "application/octet-stream"
},
encoding: null,
body: fs.createReadStream('video.mp4')
}, (error, response, body) => {
if (error) {
cb(error)
} else {
cb({response: response, body: body, url: uploadUrl,})
}
});
});
It's working when using the CURL command https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/vector-asset-api#upload-the-video . , but I need to do it in node js.
Any help is greatly appreciated :)
finally I found the solution :)
Working code
let req = request(`https://assets.mixkit.co/videos/2125/2125-720.mp4`)
.pipe(fs.createWriteStream('video.mp4'));
req.on('close', ()=>{
fs.readFile('video.mp4', function(err, data) {
if (err) throw err;
var encodedImage = new Buffer(data)
request({
url: url,
method: 'PUT',
headers: {
"x-amz-server-side-encryption-aws-kms-key-id": "MY_ID",
"x-amz-server-side-encryption": "aws:kms",
"Content-Type": "application/octet-stream"
},
encoding: null,
body: encodedImage
}, (error, response, body) => {
if (error) {
cb(error)
} else {
cb({response: response, body: body, url: url, access_token: access_token, data: ''})
}
});
});
});
Related
I am trying to send the username of a logged-in person from the Client to the Server as a string. I am already sending a file (image) but I also want to send a string as well.
Essentially what I wanna do is in the Server Side File to replace the 'public_id' with username from Client-side.
As you can see below I am already sending the image (file) that I want to the server. I have used console.log(loggedInUser?.username); to show the string that I want to be sent.
Hope this was enough to explain what I am trying to do. Thanks in advance.
Client Side file
console.log(loggedInUser?.username);
const uploadImage = async (base64EncodedImage: string) => {
try {
await fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({ data: base64EncodedImage }),
headers: { 'Content-type': 'application/json' },
});
} catch (error) {
console.error(error);
}
};
Server side file
app.post("/api/upload", async (req, res) => {
try {
const fileStr = req.body.data;
const uploadedResponse = await cloudinary.uploader.upload(fileStr, {
upload_preset: "geekyimages",
public_id: "public_id",
invalidate: true,
});
console.log(uploadedResponse);
res.json({ msg: "Uploaded" });
} catch (error) {
res.status(500).json({ err: "Something went wrong" });
}
});
Just send both inside a single JSON-Object:
// client side
await fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({
data: base64EncodedImage,
username: loggedInUser?.username
}),
headers: { 'Content-type': 'application/json' },
});
// server side
const username = req.body.username;
From here
await fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({ data: base64EncodedImage }),
headers: { 'Content-type': 'application/json' },
});
Just add a username in the body like
await fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({ data: base64EncodedImage, username: username: loggedInUser?.username || "SOME_DEFAULT_VALUE" }), // The default value is in case you an have a null or undefined username
headers: { 'Content-type': 'application/json' },
You can also prevent this behavior adding this check
if (loggedInUser?.username) ... // The code without default value
else { // A message }
I'm trying to upload a photo on Google Photos, with google api, but i always get this error:
"status":{"code":3,"message":"Failed: There was an error while trying to create this media item."}}
I think that the problem is in the way i take the binary data of photo.
In this code i follow google photo api developers documentation, and it says, after take authorization, to:
1- Upload the raw bytes to a Google Server: to take upload-token
2- Use the upload token to create the media item.
This my node js code:
const photo = fs.readFileSync("fbimages/"+req.session.id_client+"/Prague/2020-05-30T17:29:14+0000_0.png", {
'encoding': 'binary',
'flag' : 'r'
});
var url= 'https://photoslibrary.googleapis.com/v1/uploads';
var headers= {
'Authorization': 'Bearer '+token,
'Content-type': 'application/octet-stream',
'X-Goog-Upload-Content-Type': 'image/png',
'X-Goog-Upload-Protocol': 'raw',
'X-Goog-Upload-File-Name': "2020-05-30T17:29:14+0000_0.png",
};
var body= photo
request({
url: url,
method:'POST',
headers: headers,
rejectUnauthorized: false,
body: JSON.stringify(body)
}, function(error, response, body1){
if(error)
{
console.log(error);
}
else
{
var upToken = body1.toString();
console.log(upToken);
var url= 'https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate';
var headers= {
'Authorization' : 'Bearer '+token,
'Content-type': 'application/json',
};
var body= {
'newMediaItems': [
{
'description': 'Prague',
'simpleMediaItem': {
'fileName': 'prova',
'uploadToken': upToken,
}
}
]
};
request({
url: url,
method: 'POST',
headers: headers,
rejectUnauthorized: false,
body: JSON.stringify(body),
}, function(error, response, body){
if(error)
{
console.log(error);
}
else
{
res.send(JSON.parse(body));
}
});
}});
Please help me, if anyone has any idea!!
How about this modification?
Modification points:
I think that encoding: "binary" is not required.
In this case, ``const photo = fs.readFileSync("fig1.png", { flag: "r" });andconst photo = fs.readFileSync("fig1.png");` can be used.
Please modify body: JSON.stringify(body) to photo of const photo = fs.readFileSync("fig1.png", { flag: "r" });.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
const photo = fs.readFileSync("fbimages/"+req.session.id_client+"/Prague/2020-05-30T17:29:14+0000_0.png", {
'encoding': 'binary',
'flag' : 'r'
});
var url= 'https://photoslibrary.googleapis.com/v1/uploads';
var headers= {
'Authorization': 'Bearer '+token,
'Content-type': 'application/octet-stream',
'X-Goog-Upload-Content-Type': 'image/png',
'X-Goog-Upload-Protocol': 'raw',
'X-Goog-Upload-File-Name': "2020-05-30T17:29:14+0000_0.png",
};
var body= { 'media-binary-data': photo }
request({
url: url,
method:'POST',
headers: headers,
rejectUnauthorized: false,
body: JSON.stringify(body)
}, function(error, response, body1){
To:
const photo = fs.readFileSync("fbimages/"+req.session.id_client+"/Prague/2020-05-30T17:29:14+0000_0.png", { flag: "r" });
var url = "https://photoslibrary.googleapis.com/v1/uploads";
var headers = {
Authorization: "Bearer " + token,
"Content-type": "application/octet-stream",
"X-Goog-Upload-Content-Type": "image/png",
"X-Goog-Upload-Protocol": "raw",
"X-Goog-Upload-File-Name": "2020-05-30T17:29:14+0000_0.png",
};
request(
{
url: url,
method: "POST",
headers: headers,
rejectUnauthorized: false,
body: photo,
},
function (error, response, body1) {
Note:
In this modification, it supposes that your token can be used for this API. Please be careful this.
When you want to directly put the uploaded image to an alubmn, please include albumId for requesting to https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate.
Reference:
Upload media
I have several API Get request at once in nodejs. Each API have new data every couple minutes.
var express = require('express');
var router = express.Router();
var request = require("request");
let value1, value2, bodyData1, bodyData2;
var options = { method: 'GET',
url: 'https://api.example.com/data1',
qs:
{
valueType: 'MAXIMUM'
},
headers:
{
authorization: 'ABC123456',
accept: 'application/json; charset=utf-8' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
bodyData1 = JSON.parse(body);
value1 = bodyData1.value;
});
var options = { method: 'GET',
url: 'https://api.example.com/data2',
qs:
{
valueType: 'MAXIMUM'
},
headers:
{
authorization: 'ABC123456',
accept: 'application/json; charset=utf-8' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
bodyData2 = JSON.parse(body);
value2 = bodyData2.value;
});
router.get('/', function(req, res, next) {
res.render('home', {valueA : value1, valueB: value2});
});
module.exports = router;
I want to know if it is possible to combine them into one function?
Any other things I should concern?
It is possible if you have promises which is currently not the case. You have to wrap your request() call in a Promise. You can do it manually with a custom function requestToPromise.
You can then use Promise.all to call multiple promises in parallel.
function requestToPromise(options) {
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) return reject(error);
resolve(body);
});
});
}
var optionsRequest1 = {
method: "GET",
url: "https://api.example.com/data1",
qs: {
valueType: "MAXIMUM"
},
headers: {
authorization: "ABC123456",
accept: "application/json; charset=utf-8"
}
};
var optionsRequest2 = {
method: "GET",
url: "https://api.example.com/data2",
qs: {
valueType: "MAXIMUM"
},
headers: {
authorization: "ABC123456",
accept: "application/json; charset=utf-8"
}
};
var requestPromise1 = requestToPromise(optionsRequest1);
var requestPromise2 = requestToPromise(optionsRequest2);
Promise.all([requestPromise1, requestPromise2]).then(results => {
var [resultPromise1, resultPromise2] = results;
}).catch(error => {
//handle error
});
Instead of using the custom function requestToPromise you can also use util.promisify
const util = require('util');
const requestAsync = util.promisify(request);
Promise.all([requestAsync(optionsRequest1), requestAsync(optionsRequest2)]).then(results => {
var [resultPromise1, resultPromise2] = results;
}).catch(error => {
//handle error
});
You can use Redis cache to store data in memory for fast retrieval and fetch from memory very quickly.
Also, after some interval, you can add them to a database through bulk creation. It will decrease your database call.
// Example in sequilize
await db.table_name.bulkcreate([ {0bj1}, {obj2}..,{obj3 } ]);
app.get('/profile/:id', function(req, res){
var options = { method: 'GET',
url: 'https://api.favoriot.com/v1/streams?max=1',
headers:
{ 'cache-control': 'no-cache',
'content-type': 'application/json',
'apikey': 'api key' } };
request(options, function (error, response, body) {
res.render('profile', {data:body});
console.log(body)
});
});
when I run code above, I get this data:
{"debugCode":null,"statusCode":200,"numFound":1,"results":[{"user_id":"xxx510","stream_created_at":"2019-03-05T16:13:01.982Z","stream_developer_id":"f8b8fcb9-6f3e-4138-8c6b-d0a7e8xxxxx#xxxx510","device_developer_id":"raspberryPIxx#xxx510","data":{"distance":"12.4","status":"1"}}]}
how can I make it only display status only?
AFAIK there is no issue with the code as such. Are you sure that you got the distance and status in the data field of body or is it the intended output? By try using their API playground by setting your API key on it. I have rewritten the code using ES6 standards by promisifying request module or you can use the request-promise-native.
function requestPromisified(options) {
return new Promise(function(resolve, reject) {
request(options, function(error, res, body) {
if (!error && res.statusCode == 200) {
resolve(body);
} else {
reject(error);
}
});
});
}
app.get("/profile/:id", async (req, res) => {
const options = {
method: "GET",
url: "https://api.favoriot.com/v1/streams?max=1",
headers: {
"cache-control": "no-cache",
"content-type": "application/json",
apikey: "api key"
}
};
try {
const body = await requestPromisified(options);
console.log(body);
res.render("profile", { data: body });
} catch (error) {
res.status(400).send('Unable to find a profile')
}
});
1) There is no middleware in this example... you're just making a call to get some data.
2) status is available in body.results[0].data.status so just use that instead of the entire body object
I am trying to upload 3 photos from frontend using formData. It will call an external API to make the upload. But encountered some errors as below.
Frontend upload
const formData = new FormData()
formData.append('photoA', this.photoA)
formData.append('photoB', this.photoB)
formData.append('photoC', this.photoC)
axios.post(`http://localhost:4172/uploadDocs`,
{
data: formData,
accessToken: store.state.token
},
{ headers: {
// 'Content-Type': 'Application/json',
// 'x-access-token': localStorage.getItem('token')
}
}
).then (function (response) {
return response.data
})
Nodejs upload API
async uploadDocs (req, res) {
const options = {
method: "POST",
url: "https://example.com/api/v1/users/uploadDocuments?access_token=" + req.body.accessToken,
headers: {
//"Authorization": "Basic " + auth,
//"Content-Type": "multipart/form-data"
},
data: req.body.data
};
try {
request(options, function (err,response,body){
if (err) {
res.send(err)
} else {
res.send(response.body)
}
})
} catch (error) {
res.status(400).send({
error: "Server error."
})
}
}
So there are 2 errors here:
a) Frontend error: It keeps giving Cannot POST / error in html
b) Backend error:
<h1>Cannot read property 'photoA' of undefined</h1>
<h2></h2>
<pre></pre>
Been struggling with this for days. Any help will be very much appreciated.