Can't fetch file with XMLHttpRequest in React Native - javascript

I'm trying to retrieve a local file on an iOS device which is saved from Expo Camera and ImageManipulator. The Image shows up in a View. However, when I run this code to get a blob and then upload to Firebase Storage, I get the 'Network request failed error', it seems random and I don't know what causes it.
The code is from here: https://github.com/expo/expo/issues/2402#issuecomment-443726662
const blob = yield new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
//console.log(e);
reject('Network request failed.');
};
xhr.responseType = 'blob';
xhr.open('GET', uri, true);
xhr.send(null);
})
.catch(e => console.log(e));

Related

How to Upload txt file with Cypress for API Testing - XMLHTTPRequest?

I'm trying to test an endpoint which will upload a file and give 200 response status code in cypress. As per some research cy.request cannot be used to upload a file for multipart/form-data so we need to use XMLHttp to upload such files. I have created below file to test the api but it doesn't work. Can someone please help what's wrong with my code ? Thank you.
Added below code under support/commands.ts(I will require a header to pass token from auth endpoint)
// Performs an XMLHttpRequest instead of a cy.request (able to send data as FormData - multipart/form-data)
Cypress.Commands.add('multipartFormRequest', (method,URL, formData,headers, done) => {
const xhr = new XMLHttpRequest();
xhr.open(method, URL);
xhr.setRequestHeader("accept", "application/json");
xhr.setRequestHeader("Content-Type", "multipart/form-data");
if (headers) {
headers.forEach(function(header) {
xhr.setRequestHeader(header.name, header.value);
});
}
xhr.onload = function (){
done(xhr);
};
xhr.onerror = function (){
done(xhr);
};
xhr.send(formData);
})
Test file to call multipartFormRequest:
const fileName = 'test_file.txt';
const method = 'POST';
const URL = "https://fakeurl.com/upload-file";
const headers = api.headersWithAuth(`${authToken}`);
const fileType = "application/text";
cy.fixture(fileName, 'binary').then((res) => {
const blob = Cypress.Blob.binaryStringToBlob(res, fileType);
const formData = new FormData();
formData.append('file', blob, fileName);
cy.multipartFormRequest(method, URL, headers, formData, function (response) {
expect(response.status).to.equal(200);
})
})
I'm getting this error message:-
Now, I'm getting status code as 0.
describe("Upload image", () => {
it("upload first image", () => {
const fileName = "image.jpeg";
const method = "POST";
const url = "https://api-demo.com/1";
const fileType = "image/jpeg";
cy.fixture(fileName, "binary")
.then((txtBin) => Cypress.Blob.binaryStringToBlob(txtBin))
.then((blob) => {
const formData = new FormData();
formData.append("image_data", blob, fileName);
formData.append("image_format", "jpeg");
cy.form_request(method, url, formData, function (response) {
expect(response.status).to.eq(200)
}
);
})
});
});
Cypress.Commands.add('form_request', (method, url, formData, done) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader("device", "331231");
xhr.setRequestHeader("city", "bangalore");
xhr.onload = function () {
done(xhr);
};
xhr.onerror = function () {
done(xhr);
};
xhr.send(formData);
})
Use
const blob = Cypress.Blob.binaryStringToBlob(res, fileType);
and remove the .then().
See Cypress.Blob
History
Version 5.0.0
Changes:
Return type of arrayBufferToBlob, base64StringToBlob, binaryStringToBlob, and dataURLToBlob methods changed from Promise<Blob> to Blob

HTTP request to challonge API returns error 422

I'm trying to create a tournament using api.challonge.com
When attempting to do so in node.js, it works fine with this code:
request.post("https://api.challonge.com/v1/tournaments.json", {
"json":{
"api_key":API_KEY,
"name":"MyTourney",
}
}, function (error, response, body) {
console.log(body);
});
However, when attempting to do it with an XMLHttpRequest in javascript, I am getting error 422. This is the code:
var fd = new FormData();
fd.append("api_key", API_KEY);
fd.append("name", "MyTourney");
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://api.challonge.com/v1/tournaments.json", true);
xhr.onreadystatechange = function() {
console.log(xhr.responseText);
};
xhr.send(fd);
I don't understand why the request is successful in the node request, but not in the XMLHttpRequest
Here is a screenshot of the browser console:

How can i apply callback to get the http response in a method

I am attempting to write a method so that i pass the url and application name and it return the response. I read that I can apply callback to resolve this but I am not able to resolve the issue. Any help would be appreciated.
Please find below my code snippet.
var response = getResponse(url,applicationName)
console.log("response from getResponse \n" +response);
function getResponse(url,applicationName){
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
"application": applicationName
}));
xhr.onload = function() {
console.log(this.responseText);
}
return xhr.responseText;
}
You can use the onreadystatechange method to handle XHR responses, try this:
//XHR POST
const xhr = new XMLHttpRequest; // creates new object
const url = 'https://api-to-call.com/endpoint';
const data = JSON.stringify({"application": applicationName}); // converts data to a string
xhr.responseType = 'json';
xhr.onreadystatechange = () => {
if(xhr.readyState === XMLHttpRequest.DONE) {
return xhr.response;
}
}
xhr.open('POST', url); // opens request
xhr.send(data); // sends object
you should use promise instead of callback and do something like that.
const url = "https://httpbin.org/post";
const applicationName = "test";
getResponse(url, applicationName)
.then(response => {
//work here, not outside
console.log(response);
})
.catch(error => {
console.log(error);
})
function getResponse(url, applicationName) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
"application": applicationName
}));
xhr.onload = function() {
// print JSON response
if (xhr.status >= 200 && xhr.status < 300) { // if valid
// work here
const response = JSON.parse(xhr.response.replace(/"/g, '"'));
const data = JSON.parse(response.data.replace(/"/g, '"'));
resolve(data);
}
reject(xhr.response); // reject and return the response if not valid
}
})
}
If you want to learn more about asynchronous https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Concepts, I invite you to go to this website to learn a little more about the promise.
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Promises
The callback is executed after the code returned xhr.responseText. So that means xhr.responseText returns null.
I would recommend using the fetch API opposed to the older XMLHttpRequest you are using now. The fetch API is basically a Promise based XMLHttpRequest.
Your function would look something like:
async function getResponse( url, applicationName ) {
const json = JSON.stringify({
"application": applicationName
});
return fetch( url, {method: 'POST', headers: { 'Content-Type':'application/json'}, body: json} );
}
// access like this
getResponse( url, applicationName)
.then( response => { console.log(response) });
async function someFunction( url, applicationName ) {
// or pause the code while the request is fetched by using await, note that you need to be in a function that is declared async to use this approach.
const response = await getResponse( url, applicationName );
}
Fetch documentation can be found at MDN: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

Download file (any kind) from Firebase Storage in web browser ReactJS

I can't understand how the file download mechanism works. My problem is that it is missing the header CORS 'Access-Control-Allow-Origin'. I don't know where I have to put it. Is there a tutorial that explains how to use it?
My code:
const downloadFile = filePathStorage => {
storage.ref().child(filePathStorage).getDownloadURL()
.then(url => {
var xhr = new XMLHttpRequest();
xhr.responseType = "blob";
xhr.onload = function(event) {
var blob = xhr.response;
}
xhr.open("GET", url);
xhr.send();
})
.catch(err => {
console.log("download file error: " + JSON.stringify(err))
message.error("Se produjo un error. Por favor, vuelva a intentarlo.")
})
}

Javascript fetch is not working, postman works fine

I have route where I can upload images, and it works fine with postman.
I`m using multer as middleware.
var data = new FormData();
data.append("file", "");
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "http://localhost:8080/file");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("Postman-Token", "a6e7543e-ef94-4d17-813d-a0a1fb4aa2b2");
xhr.send(data);
but when I`m using fetch in my react app it just return undefined
uploadImage = async (image) => {
const imageData = new FormData()
imageData.append('file', image)
const address = '/file'
const body = imageData
const response = await fetch(`http://localhost:8080${address}`, {
method: 'POST',
credentials: 'include',
body: body
})
const result = await response.json()
return result
}
Any ideas how to fix it?
I copy paste request from postman to my react app, it still doesn`t work.

Categories