Donwload file with POST method in React Native and Expo - react-native

How can I download a file using the POST method along with some headers and data (of the type: "content-type: application/x-www-form-urlencoded") in React Native?
When I send a request to the URL, the following is returned in the Response Header:
content-disposition: attachment; filename="PAPR_Pginas_Web_2.pdf"
content-type: application/pdf
date: Sun, 07 Aug 2022 13:59:00 GMT
last-modified: Thu, 01 Jan 1970 00:00:00 GMT
server: Apache
strict-transport-security: max-age=86400
x-powered-by: JSF/1.2
x-xss-protection: 1; mode=block
I'm using this code:
const donwloadPDF = async (uri) => {
const downloadInstance = FileSystem.createDownloadResumable(uri, FileSystem.documentDirectory + "file.pdf");
const result = await downloadInstance.downloadAsync();
if (result.status === 200) {
Sharing.shareAsync(result.uri, { dialogTitle: "Share or Save" });
} else {
console.log("Failed to Download");
}
};
const getFile = async (payload) => {
try {
const response = await fetch(URL, {
method: "POST",
headers: headers2,
body: formBody(payload),
});
const content = await response.json();
donwloadPDF(content); // Some URI
} catch (error) {
console.error(error);
}
};
But is returned the error: JSON Parse error: Unrecognized token '%'

Related

vuejs axios download get filename

I'm downloading a file from an asp net API, but I can't get the filename with the extension sent from the server, in the browser I can see the header
"content-disposition: attachment; filename=AEDAF367-D922-470E -9D0F-09F84BDCA0AC.zip; filename*=UTF-8''AEDAF367-D922-470E-9D0F-09F84BDCA0AC.zip"
but in axios the "content-disposition" header does not arrive in the headers
headers:
content-length: "1270333"
content-type: "application/zip"
last-modified: "Wed, 27 Apr 2022 14:59:41 GMT"
my code ASP CORE
var fileName = Path.GetFileName("C:\file.zip");
Response.Headers.Add("content-disposition", "attachment;filename=" + fileName);
return PhysicalFile(reg.dirpc, MimeTypes.GetMimeType("C:\file.zip"), fileName);
my VueJS code
await api.get(url, { responseType: 'blob' }).then((response) => {
const blob = new Blob([response.data], { type: response.data.type });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
console.log('response = ', response);
const contentDisposition = response.headers['content-disposition'];
console.log('contentDisposition = ', contentDisposition);
let fileName = 'unknown';
if (contentDisposition) {
const fileNameMatch = contentDisposition.match(/filename="(.+)"/);
if (fileNameMatch.length === 2)
fileName = fileNameMatch[1];
}
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(url);
}).catch((error) => {
console.log('ERRO POST: ', error);
if (error.response) {
console.log('error data=', error.response.data);
}
}
});
thanks!
I recently get this same problem.
to solve this from the server side you need to set this response header:
Access-Control-Expose-Headers: "*"
for more secure option:
Access-Control-Expose-Headers: ["Content-Disposition","Content-Type","My-Custom-Header"]
you can add your own header you like too,
this will allow AXIOS to read those headers,
reference: https://github.com/axios/axios/issues/1946#issuecomment-958790245
good luck!

Accessing Set-Cookie value from response.headers in axios

I am using VueJS and Axios to send a request like this:
axiosAPI.get('/login/flows', {params: {id: 'string'}})
.then(res => {
console.log('cookie', res.headers)
}
In return server sends me this response:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Type
Cache-Control: private, no-cache, no-store, must-revalidate
Content-Length: 646
Content-Type: application/json; charset=utf-8
Date: Thu,xxxx 13:56:21 GMT
Set-Cookie: csrf_token=Lxv3zynm1Fua0hU0/W1+R2w=; Path=/.ory/kratos/public/; Domain=x.y ; Max-Age=31536000; HttpOnly; SameSite=Lax
Vary: Origin
Vary: Cookie
As you can see, server sends a csrf-token in Set-Cookies. but when I try to print out the headers I can not get and store the csrf-token. In addition, browser doesn't store the token at all in the storage section.
I need to use the csrf-token inside of this cookie but I don't know how I can do this?
Note: i don't have any access to back-end codes.
Maybe you can use the axios-cookiejar-support.
https://www.npmjs.com/package/axios-cookiejar-support
A medium article showing how to use it.
https://medium.com/#adityasrivast/handling-cookies-with-axios-872790241a9b
Sample (getting cookie from a login page):
const axios = require('axios');
const wrapper = require('axios-cookiejar-support').wrapper;
const CookieJar = require('tough-cookie').CookieJar;
const jar = new CookieJar();
const client = wrapper(axios.create({ jar }));
const url = '<your url>';
const params = new URLSearchParams();
params.append('username', '<username>');
params.append('password', '<password>');
client.post(`${url}/Login`, params, {
headers: {
'Accept': '*/*'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Using this will get you the whole string for that header:
const cookieHeaders = res.headers['Set-Cookie'];
After that, you could split the string in an array with
cookieHeaders.split('; ');
In the array, you can then get the specific one you need.

How to download a file from an endpoint and upload that file to S3 ?(GITLAB)

I'm actually trying to download a zip file from a Gitlab REST endpoint that is supposed to return the the repository for a given projectID.
I used axios to call the endpoint and tried to directly upload the response data to S3, but it seems to be returning a corrupt file as the zip that it returns says it cannot be opened.
I am doing the downloading of this file in a serverless function and attempting to return an S3 URL to the client.
Headers for the response
res.headers {
date: 'Wed, 19 Jan 2022 13:44:42 GMT',
'content-type': 'application/zip',
'transfer-encoding': 'chunked',
connection: 'close',
'cache-control': 'max-age=0, private, must-revalidate',
'content-disposition': 'attachment; filename="third-project-eac3ea41c782df4bee4fe07ecc3bf356f7f74f47-eac3ea41c782df4bee4fe07ecc3bf356f7f74f47.zip"',
'content-transfer-encoding': 'binary',
etag: 'W/"12ae32cb1ec02d01eda3581b127c1fee"',
vary: 'Origin',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-request-id': '01FSS9A6W1RM77TYMFM6G7HKZ8',
'x-runtime': '0.063985',
'strict-transport-security': 'max-age=31536000',
'referrer-policy': 'strict-origin-when-cross-origin',
'ratelimit-observed': '2',
'ratelimit-remaining': '1998',
'ratelimit-reset': '1642599941',
'ratelimit-resettime': 'Wed, 19 Jan 2022 13:45:41 GMT',
'ratelimit-limit': '2000',
'gitlab-lb': 'fe-17-lb-gprd',
'gitlab-sv': 'localhost',
'cf-cache-status': 'MISS',
'expect-ct': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
'report-to': '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=r6XcPGaiU7JhlicrSC9iBZgXXCOMoBMXjU8kvxjZGb5UkUQBIjemmAOOX39m1ijVCnQROVhNNxc6B%2B4x%2FNf5ZG9cc8GLY%2BfMYUE29gJkHN624QKJRSX8HBrMqEQ%3D"}],"group":"cf-nel","max_age":604800}',
nel: '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}',
server: 'cloudflare',
'cf-ray': '6d007fcb7a8a8e63-PDX'
}
This it the code I'm using
const requestURL = `https://gitlab.com/api/v4/projects/${repoID}/repository/archive.zip?sha=${commitSHA}`;
let url = await Axios({
method: "GET",
url: requestURL,
headers: {
Accept: "*/*",
Authorization: "Bearer " + authToken,
},
})
.then(async (res) => {
const Key = "path/to/file";
const params = {
Bucket: BUCKET_URL,
Key,
Body: res.data,
ContentType: "application/zip",
};
await s3.upload(params).promise();
const URL = await s3.getSignedUrl("getObject", {
Bucket: BUCKET_URL,
Key,
ResponseContentDisposition:'attachment; filename = test.zip"',
});
return URL ;
})
.catch((error) => {
console.log(error);
});
return url;
But when I try and access this URL on my browser from the frontend, It returns a file test.zip which is larger and corrupt.
This is a screenshot of the data that I received on postman,
if I click save response and name the file filename.zip it shows the actual contents of the file.
Any help would be appreciated!
This worked!
const requestURL = `https://gitlab.com/api/v4/projects/${repoID}/repository/archive.zip?sha=${commitSHA}`;
let url = await Axios.get(requestURL,{
headers: {
Accept: "*/*",
Authorization: "Bearer " + authToken,
},
responseType:'arraybuffer'
})
.then(async (res) => {
const bufferData = Buffer.from(res.data)
const Key = "path/to/file";
const params = {
Bucket: BUCKET_URL,
Key,
Body: bufferData,
ContentType: "buffer",
};
await s3.upload(params).promise();
const URL = await s3.getSignedUrl("getObject", {
Bucket: BUCKET_URL,
Key,
ResponseContentDisposition:'attachment; filename = test.zip"',
});
return URL ;
})
.catch((error) => {
console.log(error);
});
return url;

How to use fetch() in react native with headers json?

Postman output:
HTTP/1.0 200 OK
Cache-Control: no-cache, private
Content-Type: application/json
Date: Fri, 08 Feb 2019 12:13:36 GMT
{"status":1,"msg":"success","celeb":[{"id":1,"name":"Test Name"....
I'm getting my json in postman like this.
when I try to use fetch(), I'm getting an error json parse error, unknown identifier HTTP
fetch('https://myurl/fetch')
.then((response) => response.json())
.then((response) => {...}
let func = async () => {
const url = 'https://myurl/fetch';
const data = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: await AsyncStorage.getItem(ACCESS_TOKEN), /*or whatever you have on your api*/
}),
};
const response = await fetch(url , data);
const responseData = await response.json();
console.log(responseData);
}
I believe you are missing to set to configure you API call method, headers, mode etc... Check out Fetch Examples for a better explanation.

Angular 5 HttpClient corrupts binary downloads

When downloading a binary file from a remove server using the angular 5 http client the file is consistently corrupted. I've been unable to find resources related to this version of the client for resolving this problem. Setting the response type to either 'arraybuffer' or 'blob' does not resolve the issue.
What is the proper way to download a binary file in Angular 5 and convert it to a Uint8Array?
My current code is as follows
this.data = this.http.get(_.get(record, 'href', ''), {
observe: 'events',
reportProgress: true,
responseType: 'blob'
}))
.do(httpEvent => {
if (httpEvent.type === HttpEventType.DownloadProgress) {
this.percent.next((httpEvent.loaded / httpEvent.total) * 100);
}
})
.switchMap(httpEvent => {
if (httpEvent.type === HttpEventType.Response) {
return this.blobToArrayBuffer(httpEvent.body);
}
return Observable.of(new ArrayBuffer(0));
})
.map(buffer => {
const buff = new Uint8Array(buffer);
... // Decode buffer here
}
...
private blobToArrayBuffer(blob: Blob): Observable<ArrayBuffer> {
return Observable.create(obs => {
const fileReader = new FileReader();
fileReader.onload = () => obs.next(fileReader.result);
fileReader.onloadend = () => obs.complete();
fileReader.readAsArrayBuffer(blob);
});
}
I don't see anything obviously wrong with the response headers
HTTP/1.1 200 OK
x-amz-id-2: ...
x-amz-request-id: ...
Date: Tue, 23 Jan 2018 18:25:07 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Thu, 18 Jan 2018 22:25:33 GMT
Server: AmazonS3
ETag: ...
Accept-Ranges: bytes
Content-Type: binary/octet-stream
Content-Length: 148341
Any insight would be helpful.