I am trying to upload an image using fetch instead of xhr. My request works successfully when I use xhr. My xhr request object is the following
var data = new FormData();
var photoObject = {
uri: uriFromCameraRoll,
type: 'image/jpeg',
name: 'photo.jpg'
};
data.append("photos", photoObject);
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "http://localhost:3000/api/v1/");
xhr.send(data);
Now I am trying to use fetch like following
fetch('http://localhost:3000/api/v1/', {
mode: 'no-cors',
method: 'POST' ,
body: data
}).then(function(response) {
console.log(response.status)
console.log(response)
})
But in my sever I am not receiving the file. Can anyone help me resolve this issue?
Related
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
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
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.
I am returning stream data from laravel dompdf from this code
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML("<div>This is test</div>");
return $pdf->stream();
And this is my JS ajax code
$.ajax({
type:"GET",
url: "/display",
responseType: 'arraybuffer'
}).done(function( response ) {
var blob = new Blob([response.data], {type: 'application/pdf'});
var pdfurl = window.URL.createObjectURL(blob)+"#view=FitW";
$("#pdfviewer").attr("data",pdfurl);
});
Here is HTML to display pdf after ajax
<object id="pdfviewer" data="/files/sample.pdf" type="application/pdf" style="width:100%;height:500px;"></object>
I am getting below error
Failed to load PDF document
Please help to fix this. How to display pdf file.
jQuery.ajax() does not have a responseType setting by default. You can use a polyfill, for example jquery-ajax-blob-arraybuffer.js which implements binary data transport, or utilize fetch().
Note also, chrome, chromium have issues displaying .pdf at either <object> and <embed> elements, see Displaying PDF using object embed tag with blob URL, Embed a Blob using PDFObject. Substitute using <iframe> element for <object> element.
$(function() {
var pdfsrc = "/display";
var jQueryAjaxBlobArrayBuffer = "https://gist.githubusercontent.com/SaneMethod/"
+ "7548768/raw/ae22b1fa2e6f56ae6c87ad0d7fbae8fd511e781f/"
+ "jquery-ajax-blob-arraybuffer.js";
var script = $("<script>");
$.get(jQueryAjaxBlobArrayBuffer)
.then(function(data) {
script.text(data).appendTo("body")
}, function(err) {
console.log(err);
})
.then(function() {
$.ajax({
url: pdfsrc,
dataType: "arraybuffer"
})
.then(function(data) {
// do stuff with `data`
console.log(data, data instanceof ArrayBuffer);
$("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data], {
type: "application/pdf"
})))
}, function(err) {
console.log(err);
});
});
});
Using fetch(), .arrayBuffer()
var pdfsrc = "/display";
fetch(pdfsrc)
.then(function(response) {
return response.arrayBuffer()
})
.then(function(data) {
// do stuff with `data`
console.log(data, data instanceof ArrayBuffer);
$("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data], {
type: "application/pdf"
})))
}, function(err) {
console.log(err);
});
plnkr http://plnkr.co/edit/9R5WcsMSWQaTbgNdY3RJ?p=preview
version 1 jquery-ajax-blob-arraybuffer.js, jQuery.ajax(); version 2 fetch(), .arrayBuffer()
I like guest271314 answer a lot, especially the second version using fetch, but I wanted to add a solution that does not use a polyfill or an experimental technology like fetch.
This solution uses the native XMLHttpRequest API to create the request. This allows us to change the responseType to arrayBuffer.
var xhr = new XMLHttpRequest();
var pdfsrc = "https://upload.wikimedia.org/wikipedia/en/6/62/Definition_of_management.pdf";
xhr.open('GET', pdfsrc, true);
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", function (evt) {
var data = evt.target.response;
if (this.status === 200) {
$("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data], {
type: "application/pdf"
})));
}
}, false);
xhr.send();
I forked guest271314s plnkr to show this method in action:
http://plnkr.co/edit/7tfBYQQdnih9cW98HSXX?p=preview
From my tests the responce is in response not response.data, so the following should work:
$.ajax({
type:"GET",
url: "/display",
responseType: 'arraybuffer'
}).done(function( response ) {
var blob = new Blob([response], {type: 'application/pdf'});
var pdfurl = window.URL.createObjectURL(blob)+"#view=FitW";
$("#pdfviewer").attr("data",pdfurl);
});
Although it seems JQuery is doing something with the responce causing a blank PDF output... (PDF is blank when downloading using javascript). This will work:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'test.pdf', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var blob=new Blob([this.response], {type:"application/pdf"});
var pdfurl = window.URL.createObjectURL(blob)+"#view=FitW";
$("#pdfviewer").attr("data",pdfurl);
}
};
xhr.send();
I have an existing java client on top of which IOS, andriod developers prepared a simple http request based applications. And am trying to achieve same in HTML5 app.
And the difficulty right now am facing is sending an custom header within the AJAX request like authorization with encrypted login details.
I tried to achieve same on various REST clients and able to send "AUTHORIZATION : BASIC XXXXXX=" in request header. And getting proper json response"
But if i try same using ajax call am not able to send similar request header. Request sending as OPTIONS instead of GET and the authorization tag is not going properly as a header instead it's going as "Access-Control-Request-Headers:authorization".
and here is the snippets i have tried.
<script>
//$.ajaxSetup({ headers: { 'Authorization': 'Basic XXXXXXX='} })
// get form data for POSTING
var vFD = new FormData(document.getElementById('upload_form'));
var oXHR = new XMLHttpRequest();
oXHR.open('POST', "https://123.123.123.123:229/");
//oXHR.send(vFD);
var body = 'Basic XXXXXXX=';
var mUrl = "https://123.123.123.123:229/?json";
var client = new XMLHttpRequest();
client.open('GET', mUrl, true);
client.withCredentials = true;
client.crossDomain = true,
client.setRequestHeader('Authorization', 'Basic XXXXXXX=');
client.send(body);
simpleHttpRequest();
function simpleHttpRequest() {
alert("calling ");
var headers = {
"Authorization": "Basic XXXXXXX="
};
$.ajaxSetup({ "headers": headers });
$.ajaxSetup({ 'cache': false });
$.ajax({
type: "GET",
withCredentials: true,
// data: {
// address: 'http://www.google.com'
// },
crossDomain: true,
Headers: { "Authorization": "Basic XXXXXXX=" },
dataType: "jsonp",
url: mUrl,
cache: false
});
}
xhrToSend();
function xhrToSend() {
// Attempt to creat the XHR2 object
var xhr;
try {
xhr = new XMLHttpRequest();
} catch (e) {
try {
xhr = new XDomainRequest();
} catch (e) {
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
statusField('\nYour browser is not' +
' compatible with XHR2');
}
}
}
}
xhr.withCredentials = true;
xhr.open('GET', mUrl, true);
xhr.setRequestHeader("Authorization", "numberOfBLObsSent");
xhr.send();
};
</script>
And all the different ways getting failed. Please help me.
Thanks in advance.
The issue is related to the cross-domain nature of the request. When you make a cross-domain request which contains custom headers, the request is first "preflighted" to the server via the OPTIONS method, and the server must respond with a header Access-Control-Allow-Headers: your-custom-header. Once this is received, the ajax client will then (automatically) issue the actual request.
More on preflighted requests