How to Download Pdf File in React From Api - reactjs

I want to download pdf file by fetching from Flask db.
React code:
downloadReport(idx) {
console.log(idx)
fetch('/getDataReport', {
method: 'post',
headers: {'Content-Type':'application/json', 'Accept':'application/json', 'responseType':'arraybuffer'},
body: JSON.stringify({id: idx}),
}).then(res => res.json()).catch(error => {
console.error('Error:', error);
})
.then(response => {
console.log(response)
})
}
The above is triggered by onClick method, I get the id and put it in API body. When I give the id I want to make it download from db.
Flask code:
def getData():
req = flask.request.get_json(force=True)
id = req.get('id', None)
report = Report.query.filter_by(id=id).first()
return send_file(BytesIO(report.get_data()), attachment_filename=report.get_date()+'-report.pdf', as_attachment=True)
When I click download, Post request working fine actually. But I get "index.js:1437 Error: SyntaxError: Unexpected token % in JSON at position 0" error and my response is undefined. I couldn't solve it. Hope someone can help. Thank you in advance.
reactjs

I'd start by looking at the line where you're attempting to deserialize the response as JSON:
.then(res => res.json())
Typically when fetching a file from an endpoint, the response is handled as a blob:
.then(res => res.blob()).then((blob) => { // do what you need to do })
blob() MDN Documentation
Once you've gotten the file, then you'll need a mechanism to force the browser to download the file. There are a few NPM packages that can help with this such as downloadjs or you can roll your own.
Another StackOverflow post on the same topic

Related

Getting "TypeError: Failed to fetch" with some url

I'm facing "TypeError: Failed to fetch" errors in my React App.
Depending on the url of the query I run I sometimes encounter the error, although the query does return a valid result when I test it in my browser.
Here are two examples with two sample URL:
(function(){
var GetRequestResult = function (url) {
return fetch(url, {
headers: { 'Access-Control-Allow-Origin': '*'}})
.then(response => response.text())
.then(text => console.log(text))
.catch(error => console.log(error))
};
this.GetRequestResult = GetRequestResult;
})(this);
console.log(GetRequestResult('https://jsonplaceholder.typicode.com/comments?postId=1')); // Works
console.log(GetRequestResult('http://api.plos.org/search?q=title:DNA')); // Returns 'TypeError: Failed to fetch'
So I have two questions:
Why the first one works and not the second ?
My final need is to retrieve a response from Google's Recaptcha API (https://developers.google.com/recaptcha/docs/verify) using the URL: https://www.google.com/recaptcha/api/siteverify . I am encountering the error on this url also.
I guess it's related to CORS (I tried to modify the Headers of my requests, to define https://www.google.com as a proxy, to use different methods to execute the requests ...) but without success. Any idea to solve this problem ?
The problem is solved.
I was trying to call the Google Recaptcha API (https://www.google.com/recaptcha/api/siteverify) from my frontend.
Due to Google's CORS policy this only seems possible from the backend side.
async function getRequest() {
fetch('https://api.plos.org/search?q=title:DNA')
.then( res => res.json())
.then( data => console.log(data.response.docs))
.catch( e => console.log(e))
}
The following code is working in nodejs

Bad request status 400 when trying to upload image file to imgur

I'm trying upload image file from my React app.
Keep getting 400 error, witch I can't understand why.
That's my TypeScript function's code in React:
public setImage = (args: ChangeEvent<HTMLInputElement>) => {
const image = args.target.files[0];
let formData: FormData = new FormData();
formData.append("profileImage", image, image.name);
const requestOptions = {
method: 'POST',
headers: { 'Authorization': 'Client-ID //my client-id here//' },
image: image
};
fetch('https://api.imgur.com/3/image', requestOptions)
.then(response => response.json())
.then(data => console.log(data));
}
And the error:
{
data: error: "No image data was sent to the upload api"
method: "POST"request: "/3/image"
__proto__: Objectstatus: 400
success: false
__proto__: Object
}
When i'm trying to console my FormData object after appending I can see an empty object.
Thanks for any answer!
The first thing that comes to mind is to log the image object as well and see if there are any problems there.
Also please take a look at this to verify that you're logging your FormData object correctly.
If however, this is still not enough to debug the issue, I would advise you to try rolling a request using something like curl or Fiddler since you are manually creating the POST headers. Because of this, you're not sending the Content-Length header which could cause the imgur api to just skip the whole body of your request.
To get the content lenght you could do something like:
let content-length = JSON.stringify(formData).length;
Then simply:
const requestOptions = {
method: 'POST',
headers: { 'Authorization': 'Client-ID //my client-id here//', 'Content-Length': content-length },
image: image
};
Hope this is useful in some way.

Axios Interceptors with given token, React

After this request:
axios
.post(url_auth, obj)
.then(response => {
const info = response.data
this.setState({info})
})
.catch(error => {
console.log(error);
});
I store inside info a JSON with id and token. (backend sent it to me)
I would like now to store token in the headers of every request I made.
How do I make it with? I guess with interceptor? Once I configure the headers inside the interceptor (I'm trying to understand how), how do I call it in my request?
Thank you very much!
Yes this can be done with the interceptors.Refer this article
Also you can refer one of my repo,The project is in Angular & Node.Used Token for validating the request

send base64 string data to server but receive empty form value

I have a front-end written in Vue and a backend written in Golang. I'm using Google app engine to run my backend service, and use gcloud datastore and gcloud storage to store the data and image that were submitted through front-end form.
I've been trying to upload an image using POST method. I convert the image to a base64 string. Then I add the data string to formdata and POST to my backend service. I keep getting empty form value in Go program. Is there a reason that Go cannot read base64 string, or I miss something important about FormData? Any help helps, thank you.
My front-end code:
var myForm = document.getElementById('myForm')
var formData = new FormData(myForm)
var imgBase64 = getBase64(//image-url//)
imgBase64.then(function (res) {
formData.append('image', res)
}
axios.post(' //go-app-engine-service// ', formData)
.then(res => {
console.log(res)
})
.catch(error => {
console.log(error)
})
function getBase64(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => Buffer.from(response.data, 'binary').toString('base64'))}
My Go code:
imgString := r.FormValue("image")
fmt.Printf("imgstring: %s, %d, %T\n", imgString, len(imgString), imgString) //=> getting empty imgString
Ok, after some research I realize the "scope" issue.
function getBase64 returns a Promise and have to handle the value inside the scope, so I move the axios.post in the Promise and I finally see the base64 value in Go program. Problem solved.
modified front-end code:
var myForm = document.getElementById('myForm')
var formData = new FormData(myForm)
var imgBase64 = getBase64(//image-url//)
imgBase64.then(function (res) {
formData.append('image', res)
axios.post(' //go-app-engine-service// ', formData)
.then(res => {
console.log(res)
})
.catch(error => {
console.log(error)
})
}

React + fetch request

I am reading this article fetch API and trying to understand how to work with fetch in React. Firstly, could you explain what is request headers ?
Than,
in angular we do something like:
$http.get('/someword').success(function(response) {
console.log('i got the data i requested');
var variable = response;
}
and than on server side in express I can write:
var app = express();
app.get('/thissomeword', function(req, res) {
console.log('I got a GET request')
res.json(someVariableWithData)
})
How to do the same with fetch ? And the main question where and when I need to do it ? I understand that i need after i get data to do this.setState({}) for using my data later, but HOW is for me huge conundrum.
Here you have great facebook documentation:
https://facebook.github.io/react-native/docs/network.html
with example that shows what you want
headers in request
Sometimes you need header in request to provide access token or content-type (especially in POST request)
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
Promises instead of callbacks
In your example you pass callbacks (req and res) to your request, in fetch you have Promises so you get response as a paramether of then or error message in catch.
fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
Request Headers
As basic, Request Headers are set by the browsers and the application developers, this is use to tell the web server what the client is sending and what can it accept back in return.
Reference
Fetch
Fetch is used to make async network calls. It has a simpler API support based on promises. I'll make your code cleaner with less number of lines.
Reference

Resources