Previously I was using the Dropbox API V1 within my web app to upload files my dropbox account. Please note that the app uses only one dropbox account (mine) to upload files.
So Previously:
I created an app on the dropbox developers console
Generated my token from the developers console
Hard coded that token into my server to upload all file to a specific folder within my Dropbox.
This worked perfectly before but as the dropbox API v1 has been deprecated it does not work anymore.
Dropbox V1 Code:
function fileupload(content) {
request.put('https://api-content.dropbox.com/1/files_put/auto/my_reports/report.pdf', {
headers: {
Authorization: 'TOKEN HERE',
'Content-Type': 'application/pdf'
},
body: content
}, function optionalCallback(err, httpResponse, bodymsg) {
if (err) {
console.log(err);
}
else {
console.log("File uploaded to dropbox successfully!");
fs.unlink(temp_dir + 'report.pdf', function(err) {
if (err)
throw err;
else {
console.log("file deleted from server!");
}
})
request.post('https://api.dropboxapi.com/1/shares/auto/MY_reports/report.pdf' + '?short_url=false', {
headers: {
Authorization: 'TOKEN HERE'
}
}, function optionalCallback(err, httpResponse, bodymsg) {
if (err) {
console.log(err);
}
else {
console.log('Shared link 2 ' + JSON.parse(httpResponse.body).url);
}
});
}
});
}
Dropbox V2 Code:
function fileupload(content) {
request.post('https://content.dropboxapi.com/2/files/upload/my_reports', {
headers: {
Authorization: 'TOKEN HERE',
'Content-Type': 'application/pdf'
},
body: content
} ......... (rest of the code is similar to above)
Issue:
What I have tried does not work. I can't seem to upload a file to my dropbox account from within my app. I have tried re-generating my TOKEN from the Dropbox App console but no luck.
Can anyone tell me what am I doing wrong?
Update:
I updated my code to similar structure for v2 of the API but still unable to resolve it.
request.post('https://content.dropboxapi.com/2/files/upload/', {
headers: {
Authorization: 'Bearer TOKEN',
'Dropbox-API-Arg': {"path": "/Homework","mode": "add","autorename": true,"mute": false},
'Content-Type': 'application/pdf'
//'Content-Type': 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
},
body: content
} .... similar code
I encourage you to use existing nodejs dropbox packages, which hides abstraction of an authentication process, etc. under the hood.
Check official dropbox-sdk-js or try my tiny package dropbox-v2-api. Quick example:
const dropboxV2Api = require('dropbox-v2-api');
//create session
const dropbox = dropboxV2Api.authenticate({
token: 'TOKEN HERE'
});
//create upload stream
const uploadStream = dropbox({
resource: 'files/upload',
parameters: {
path: '/dropbox/path/to/file.txt'
}
}, (err, result) => {
// upload completed
});
//use nodejs stream
fs.createReadStream('path/to/file.txt').pipe(uploadStream);
My recommendation is also to use a SDK which abstracts over authentication. CloudRail for Node.js could be very useful here. It's quite easy to use and works for other providers like OneDrive as well.
const cloudrail = require("cloudrail-si");
const service = new cloudrail.services.Dropbox(
cloudrail.RedirectReceivers.getLocalAuthenticator(8082),
"[Dropbox Client Identifier]",
"[Dropbox Client Secret]",
"http://localhost:8082/auth",
"someState"
);
service.upload(
"/myFolder/myFile.png",
readableStream,
1024,
true,
(error) => {
// Check for potential error
}
);
Here is also a short article about the {“error”: “v1_retired”} issue.
Related
i trying host media/image files on cloudflare r2 bucket. I tried lots of stuff but I still can't reach bucket from outsite with nodeJS.
How can i fix this code?
My Final Code:
fetch('https://USER_ID.r2.cloudflarestorage.com/PROJECT_NAME/src/thumbs/BLAHBLAH', {
method: 'GET',
headers: {
'Content-Type': 'image/jpeg',
'Authorization': 'SECRET_KEY_FOR_API',
'X-Amz-Ac': 'private',
'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
'X-Amz-Date': (new Date().toISOString().split(':').join('').split('.')[0] + 'Z').split('-').join(''),
'X-Amz-Expires': '86400',
'x-amz-content-sha256': 'UNSIGNED-PAYLOAD',
}}).then(res => res.text()).then(buffer => {
console.log(buffer);
}).catch(err => {
console.log(err);
});
You'll need to implement proper SigV4 signing for your request.
It'll be easiest to use one of the AWS SDKs, like aws-sdk-js - take a look at the example documentation for R2: https://developers.cloudflare.com/r2/examples/aws-sdk-js-v3/
What I want to do is make a curl request which has an authorization token as a header and then I want to save the file in the local directory.
I am trying to use request function trying to achieve that but don't have much success of it.
it('Testing something', () => {
cy.request({
method: 'GET',
url: 'http://google.com/request',
auth: {
bearer: token
},
encoding: 'binary'
}).then((response) => {
//Validate the response
});
});
const options = {
url: `http://google.com/request/download`,
headers: {
'Authorization': `Bearer token`
},
method: 'GET'
};
const result = https.get(options, response => {
if(response.statusCode == 200){
const fileStream = fs.createWriteStream(destinationFolder);
request(response.request).pipe(fileStream);
}
});
});
Problem: When I run above code the file is not downloaded in the destination folder. I just want to download the file and that will make my test complete. I can download the file using curl request. Is there a way that we can mimic curl request in cypress test.
Note: This is a part of cypress test.
Well I figure it out how to acheive it, I am not sure if it is a right approach or not but following is my solution.
I used location in my curl request in order to download the file.
In order to make a curl request from cypress, I used cy.exec :
cy.exec{'curl request', (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
I'm trying attach an image using the bot emulator tool and sending this image off to the microsofts customvision api, the issue I'm having is that I get
{ Code: 'BadRequestImageFormat', Message: '' }
back from custom the custom vision api call.
I'm using the the request module from npm to handle the calls
// Receive messages from the user and respond by echoing each message back (prefixed with 'You said:')
var bot = new builder.UniversalBot(connector, function (session) {
session.send("Hello"); //session.message.text
// If there is an attachment
if (session.message.attachments.length > 0){
console.log(session.message.attachments[0])
request.post({
url: 'xxx',
encoding: null,
json: true,
headers: {
'Content-Type': 'application/octet-stream',
'Prediction-Key': 'xxx'
},
body: session.message.attachments[0]
}, function(error, response, body){
console.log(body);
});
}
});
I believe that I may be sending the wrong format through to custom vision however I have been unable to figure it out as of yet.
I replicated your issue and it looks like the problem is your 'Content-Type'. You're attempting to pass JSON in your request, but setting the content-type as octet-stream. See my modified code below:
var bot = new builder.UniversalBot(connector, function (session) {
session.send("Hello"); //session.message.text
// If there is an attachment
if (session.message.attachments.length > 0){
console.log(session.message.attachments[0])
request.post({
url: 'https://northeurope.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures',
encoding: null,
json: true,
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'Your API Key...'
},
body: session.message.attachments[0]
},
function (err, response, body) {
if (err) return console.log(err)
console.log(body);
});
}
});
When I run this, I get the error InvalidImageUrl which is to be expected as it's looking for a content on localhost. You could get round this by exposing your localhost using Ngrok.
From my API(nodejs), I'm accessing a third-party API (using http) to download files.
The service returns a Base64 string, chopped into smaller pieces, to be able to handle larger files.
Is it possible to do multiple http-requests (loop ?) to the third-party service, send each piece in response, to the browser until there is no longer any response from the third-party service?
The reason i want to do this, is because I don't want to consume to much memory on the node server.
I will put the pieces back together in the browser.
Any suggestions on how to do this?
See my current code below.
var request = require('request');
router.post('/getfiledata', function(req, res) {
var fileid = req.body.fileid;
var token = req.headers.authorization;
getFileData(req, res, dbconfig, fileid, token, function(err, chunkOfFile) {
if (err) {
res.status(500).send({
status: 500,
message: err
});
return;
}
res.send(chunkOfFile);
});
});
function getFileData(req, res, dbconfig, fileid, token, next) {
var url ="http://*ip*/service/rest/getfiledata";
var reqbody = {
fileId: fileid
};
var options = {
url: url,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': token
},
json: true,
body: reqbody
};
/*SOME LOOP HERE TO GET EACH CHUNK AND SEND TO BROWSER*/
request(options, function(err, resp, body) {
if (err) {
console.log(err);
next(err, undefined);
return;
} else {
next(undefined, body)
};
});
};
I think you need Socket.io to push chunks to the browser.
Server :
socket.send("chunk", chunkOfFile)
Client :
let fullString = ""
socket.on("chunk", chunkOfFile => fullString += chunkOfFile )
Something like that
The request library you are using allows for streaming of data from one source to another. Check out the documentation on github.
Here is an example from that page:
request
.get(source)
.on('response', function(response) {
console.log(response.statusCode) // 200
console.log(response.headers['content-type']) // 'image/png'
})
.pipe(request.put(destination))
You may choose to use the http module from Nodejs, as it implements the EventEmitter class too.
I ended up doing a recursive loop from the client. Sending http-requests to my API(node) until the response no longer returns any base64 data chunks.
Thank you guys!
I'm using googles drive API to download files of spreadsheet type. This works just fine except for when I try to download it in text/csv.
Is should be supported according to this page:
https://developers.google.com/drive/v3/web/manage-downloads
So this code works fine:
var request = gapi.client.drive.files.export({
'fileId': fileId,
'mimeType': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
request.then(function(response) {
console.log(response);
}, function(err) {
console.log('Error');
console.log(err.result.error);
});
This code doesn't:
var request = gapi.client.drive.files.export({
'fileId': fileId,
'mimeType': 'text/csv'
})
request.then(function(response) {
console.log(response);
}, function(err) {
console.log('Error');
console.log(err.result.error);
});
The error I get from the server is:
domain: "global"
message: "Internal Error"
reason: "internalError"
Does anyone know what could be the reason for this?
This is a known issue with the Drive API v3, and it has been raised with the engineering team. Please follow this issue for updates.