Dropbox download file API stopped working with 400 error - javascript

I use dropbox download file API , and i got a token , but it's return 400 bad request error
"Error in call to API function "files/download": Must provide HTTP header "Authorization" or URL parameter "authorization"
I follow dropbox api doc , but it cannot work ~""~
How do I fix it ?
this is my code ( angular2 )
downloadFile(fileid){
let headers = new Headers();
headers.append('Authorization', 'Bearer ' + this.accessToken);
headers.append('Dropbox-API-Arg','path:'+ fileid);
return this.http.post('https://content.dropboxapi.com/2/files/download',new RequestOptions({ headers: headers ,responseType:ResponseContentType.ArrayBuffer})).map((res) => {
let arrayBuffer = res.arrayBuffer();
let contentType = res.headers.get('content-type');
return {
fileid: fileid,
blob: new Blob([arrayBuffer], { type: contentType })
};
});

I use dropbox v2 api in android. Just as you, I got 400 bad request. It turns out that Android HttpUrlConnection set a default "Content-Type" header value. And dropbox download api require "Content-Type" to be missing or empty. I don't have same issue in iOS though.
So maybe in angular2, you need to do something like:
headers.append('Content-Type','');
Also the 'Dropbox-API-Arg' header need to be like:
headers.append('Dropbox-API-Arg','{\"path\": \"/filepath\"}');

Related

Uploading file, axios works but fetch API doesn't, what did I do wrong?

I'm using fetch API to communicate with the server, then I realize when I use fetch API to upload file, the post request looks weird and my PHP server couldn't get the file by $_FILES correctly.
Here's my basic setup, the file and fileName are pre-populated.
const api = 'xxxx/api/file';
const body = new FormData();
body.append('files[]', file, fileName);
body.append('bid', 529);
const headers = {
'Content-Type': 'multipart/form-data',
'Authorization': 'Token xxxxxx'
};
While I'm using fetch API, the post request looks like this, any my PHP server couldn't get the post data.
fetch(api, { method: 'POST', body, headers, mode: 'cors' });
But when I use axios, the request looks like this, and my PHP server could get the files correctly:
axios.post(api, body, { headers });
So what is going on? Did axios do something different?
And is there a way to achieve this without using axios?
Try the fetch API without the content-Type key:
const api = 'xxxx/api/file';
const body = new FormData();
body.append('files[]', file, fileName);
body.append('bid', 529);
const headers = {
'Authorization': 'Token xxxxxx'
};
delete headers.headers['Content-Type'];
fetch(api, { method: 'POST', body, headers, mode: 'cors' });
Source: https://muffinman.io/blog/uploading-files-using-fetch-multipart-form-data/

403 on `PUT` request on signed url for S3 image upload using lamda

I was trying to create an image uploader to my S3 bucket using a Lambda. But when I try to do a PUT request on the generated signed URL from the lambda I am getting a 403.
I have configured my lambda to be able to s3:putObject and s3:putObjectACL
I have also tried to make my s3 bucket public to allow read and write to it for Everyone and have also enabled CORS on my s3 bucket along with my API lambda trigger endpoint.
I am still getting a 403 forbidden when I try to upload an image from my client-side HTML page.
The function is like this:
const uploadS3 = async (uri) =>{
const file = new Image();
file.src = uri;
const url = "API-Endpoint to trigger LAMBDA";
fetch(url,
{
//fetches the signed url
method: 'GET',
mode:'cors',
})
.then((res) => res.json())
.then((response)=> {
console.log(response);
console.log(response.uploadURL);
// request to try to PUT image to s3 bucket using the signed url
fetch(response.uploadURL,{
method: 'PUT',
headers: {
"Content-Type": "image/png"
},
mode:'cors',
body: file
})
.then((res)=> console.log(res))
.catch((res)=> console.log(res))
})
.catch((err)=>console.log(err))
}
Where am I going wrong?
Really thankful for your help !!
You need the following headers both when getting the presigned URL on server side and when making the request on the client side with the presigned URL
{ headers: { 'Content-Type': 'image/jpeg', 'x-amz-acl': 'public-read' } };

Send file with form-data and axios

I am trying to send a video to a videosite, I am able to upload the video using the REST api and postman, so I know the api works as intended. Now I want to do exatcly the same request using axios. I have code that looks like the example on how to use form-data and axios:
const form = new FormData();
const stream = fs.createReadStream(PATH_TO_FILE);
form.append('image', stream);
// In Node.js environment you need to set boundary in the header field 'Content-Type' by calling method `getHeaders`
const formHeaders = form.getHeaders();
axios.post('http://example.com', form, {
headers: {
...formHeaders,
},
})
.then(response => response)
.catch(error => error)
I get the error that data: 'Content-Length is required'
Any ideas?
May be I got your questions wrong , you want to add Content-Length in the header.
I can see you are uploading video stream. So first you have to calculate the data chunk length.
('Content-Length', File.getSize(stream))
Reference: Can I stream a file upload to S3 without a content-length header?
You can make the post request as multi-part type : 'Content-Type': 'multipart/form-data'.
It is preferable way to send large data to server.
You can check this link : How do I set multipart in axios with react?
If I got your question wrong , plese comment or reply . Thanks
The solution to my problem was to set Content-Length accordingly:
"Content-Length": fs.statSync(filePath)['size']
I think the best way to handle this is to actually use the FormData's own method:
const headers = { 'content-length': formData.getLengthSync(), ...formData.getHeaders() }
This will be more accurate because it includes any other data you may add.
To expound, if you are using a ReadStream, you must use the async function instead.
const { promisify } = require('util')
const getLength = promisify(formData.getLength.bind(formData))
const contentLength = await getLength()
const headers = { 'content-length': contentLength, ...formData.getHeaders() }

Upload Image to Azure Blob container using Axios [VueJs]

I am trying to using Axios PUT function to upload an image to Azure Storage.
What I did is as following:
I created a storage account in Azure, then I Add CORS rule as following: CORS rule
I created a Blob with name user-pic.
I use Axios to make the request for me
code:
function upload(formData) {
//get the current date
var currentdate = new Date();
var Curr_date = currentdate.getDay + '-' + currentdate.getMonth + '-' + currentdate.getFullYear;
//Here I am trying to convert the image to binary encoding.
var data = btoa(formData);
//The image Url, [ below there is an example from where I take this url ].
const url = "https://XXXXXXX.blob.core.windows.net/XXXXXXXXXXXX";
//Headers are required for me, do I need to add all Headers in my code also in CORS of the storage account?
axios.put(url, data {
headers: {
"Access-Control-Allow-Origin" : "*",
'Access-Control-Allow-Methods': 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
"Access-Control-Allow-Headers": "Origin, Content-Type, x-ms-*",
"Content-Type": "image/png",
"Content-Length": data.length, //here I am trying to get the size of image.
"x-ms-date": Curr_date,
"x-ms-version": sv,
"x-ms-blob-type": "BlockBlob",
}
})
.then ( response => { console.log(response); console.log('correct!!'); } )
.catch ( error => { console.log(error); console.log('error here!!'); });
}
What I mean by the comments inside the code:
The image URL should be at the same format of this: Blob SAS Url
Is the format of Curr_date is correct to be accepted by x-ms-date header?
Is function btoa used to convert the image to binary encoding?
Should I add all headers in Axios into account storage CORS (in the header field)?
What is the correct method to get the size of the image? (.size function? actually, I am passing the formData after appending all images into it.
After running the program, in the console, I got two error messages:
How can I solve these problems?
Update:
I made these changes:
I change the CORS: CORS
I got this error msg: Error Msg
Your CORS rule defined for your Azure Storage is missing your http://localhost origin.

Angular 2 Http with custom headers getting 405

I've run into this issue with custom headers when trying to perform and Http GET request from angular 2. Preforming the same request from Postman works fine, however I get a following 405 error in Angular2:
OPTIONS http://[somehost.com]/api/v1/admin/account/singin 405 (Method Not Allowed)
The API has a GET operation where you pass a username and password in the header and it returns a 200 with a token in it's header. Here is an example of the code block I am using:
constructor (private http: Http) {
}
login (userName: string, password: string): Observable<any> {
const endPointUrl = this.baseUrl + '/admin/account/singin';
const headers = new Headers({
'Accept': 'application/json',
'X-Rem-Username': userName,
'X-Rem-Password': password
});
const options = new RequestOptions({headers: headers});
return this.http.get(endPointUrl, options)
.map((response: Response) => {
console.log(response);
return response;
});
}
As I mentioned, performing this request in Postman and in he WebStorm REST client with these headers works fine. If I remove these 'X-Rem' headers I get a 401, which is expected. Any help would be appreciated, thanks.
Try this
const headers = new Headers({
'Accept': 'application/json',
'X-Rem-Username': userName,
'X-Rem-Password': password
});
this.http.get('url', {headers: headers})
This is not problem with angular app. Your app and rest api server are different server/domain. You should configure cross domain allow in server. Whenever you request any api on server by web browser, it first check cross domain allow options by request a OPTION method. In postman api directly send, there is no cross domain.
I am not sure but you can try add this header:
"Access-Control-Expose-Headers" : "Authorization"
I found it in this discussion

Categories

Resources