how to find out if XMLHttpRequest.send() worked - javascript

I am using XMLHttpRequest to send a file from javascript code to a django view.I need to detect,whether the file has been sent or if some error occurred.I used jquery to write the following javascript.
Ideally I would like to show the user an error message that the file was not uploaded.Is there some way to do this in javascript?
I tried to do this by returning a success/failure message from django view , putting the success/failed message as json and sending back the serialized json from the django view.For this,I made the xhr.open() non-asynchronous. I tried to print the xmlhttpRequest object's responseText .The console.log(xhr.responseText) shows
response= {"message": "success"}
What I am wondering is,whether this is the proper way to do this.In many articles,I found the warning that
Using async=false is not recommended
So,is there any way to find out whether the file has been sent,while keeping xhr.open() asynchronous?
$(document).ready(function(){
$(document).on('change', '#fselect', function(e){
e.preventDefault();
sendFile();
});
});
function sendFile(){
var form = $('#fileform').get(0);
var formData = new FormData(form);
var file = $('#fselect').get(0).files[0];
var xhr = new XMLHttpRequest();
formData.append('myfile', file);
xhr.open('POST', 'uploadfile/', false);
xhr.send(formData);
console.log('response=',xhr.responseText);
}
My django view extracts file from form data and writes to a destination folder.
def store_uploaded_file(request):
message='failed'
to_return = {}
if (request.method == 'POST'):
if request.FILES.has_key('myfile'):
file = request.FILES['myfile']
with open('/uploadpath/%s' % file.name, 'wb+') as dest:
for chunk in file.chunks():
dest.write(chunk)
message="success"
to_return['message']= message
serialized = simplejson.dumps(to_return)
if store_message == "success":
return HttpResponse(serialized, mimetype="application/json")
else:
return HttpResponseServerError(serialized, mimetype="application/json")
EDIT:
I got this working with the help of #FabrícioMatté
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200){
console.log('xhr.readyState=',xhr.readyState);
console.log('xhr.status=',xhr.status);
console.log('response=',xhr.responseText);
var data = $.parseJSON(xhr.responseText);
var uploadResult = data['message']
console.log('uploadResult=',uploadResult);
if (uploadResult=='failure'){
console.log('failed to upload file');
displayError('failed to upload');
}else if (uploadResult=='success'){
console.log('successfully uploaded file');
}
}
}

Something like the following code should do the job:
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4) {
var response = JSON.parse(xmlhttp.responseText);
if (xmlhttp.status === 200) {
console.log('successful');
} else {
console.log('failed');
}
}
}

XMLHttpRequest objects contain the status and readyState properties, which you can test in the xhr.onreadystatechange event to check if your request was successful.

XMLHttpRequest provides the ability to listen to various events that can occur while the request is being processed. This includes periodic progress notifications, error notifications, and so forth.
So:
function sendFile() {
var form = $('#fileform').get(0);
var formData = new FormData(form);
var file = $('#fselect').get(0).files[0]
var xhr = new XMLHttpRequest();
formData.append('myfile', file);
xhr.open('POST', 'uploadfile/', false);
xhr.addEventListener("load", transferComplete);
xhr.addEventListener("error", transferFailed);
}
function transferComplete(evt) {
console.log("The transfer is complete.");
// Do something
}
function transferFailed(evt) {
console.log("An error occurred while transferring the file.");
// Do something
}
You can read more about Using XMLHttpRequest.

Related

I can't get a response from the server

I followed some guides on how to send json objects to the server(written using node.js) and it doesn't work, I have no idea what is wrong. I know that my server works fine since I tested it on postman so it's my js code that's the problem, all the tutorials I see follow a similar XMLHttpRequest format.
this is my code
var ing = new Ingredient(name, date, qty, rp);
var url = "http://localhost:8081/addIngredient";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
//Send the proper header information along with the request
// application/json is sending json format data
xhr.setRequestHeader("Content-type", "application/json");
// Create a state change callback
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// Print received data from server
result.innerHTML = this.responseText;
}
};
// Converting JSON data to string
var data = JSON.stringify(ing);
document.write(data);
// Sending data with the request
xhr.send(data);
I used document.write to check where the code stops working but everything passes (since the document.write prints something), I suspect that there is something wrong/missing from xhr.send(data) but I can't tell what. Finally, nothing gets printed from the callback.
It's better to use onload instead of onreadystatechange
xhr.onload = function() {
if (xhr.status == 200) {
console.log(`Response length = ${xhr.response.length}`);
// store xhr.response here somewhere
}
};

How to handle a POST request error using XMLHttpRequest() and Javascript

I am trying to handle an error thrown by a HTTP request, but am unable to properly intercept the event.
POST http://localhost:8080/path/to/endpoint 500 (Internal Server Error)
I have a drop zone on the page that receives a file and parses it on a server. When the file is properly formatted it works well, but am trying to handle errors caused by improperly formatted documents.
According to the Mozilla docs the XMLHttpRequest has an onerror function, but it's getting bypassed when I try to use it as follows:
_postRequest() {
let files = this.files[0];
let data = new FormData();
let request = new XMLHttpRequest();
// File selected by the user - in case of multiple files append each of them
data.append('file', this.files[0]);
// AJAX request finished
request.addEventListener('load', (e) => {
// Send response to DOM
this.dispatchEvent(new CustomEvent('return-validated-items', {
bubbles: true, composed: true,
detail: request.response
}));
});
// If server is sending a JSON response then set JSON response type
request.responseType = 'json';
// Send POST request to the server side script
request.open('post', 'http://localhost:8080/path/to/endpoint');
request.onerror = function () { // This function is not working properly
console.log("** An error occurred during the transaction");
};
request.send(data);
}
I was also having issues with this alternative method:
try {
request.open('post', 'http://localhost:8080/path/to/endpoint');
request.send(data);
} catch (e) {
console.log(e)
}
How can I handle an error caused by request.send()?
The load event should get the message. Look at the status there
request.addEventListener('load', (e) => {
console.log(e.currentTarget.status) // or request.status
})
so you can do something like
request.addEventListener('load', (e) => {
if (request.status < 400) {
dispatchIt()
} else {
displayError()
}
})

Why is formData not a constructor?

I am working with a TinyMCE editor and I've followed their demo and another tutorial to the 'T'. My goal is to use the image uploader to enable the user to upload images to the server.
However, when I use the image uploader to select an image, the error "formData is not a constructor" pops up.
error message
Here is the JavaScript code:
images_upload_handler: function (blobInfo, success, failure) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', 'upload.php');
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
};
formData = new FormData();
formData.append('file', blobInfo.blob(), fileName(blobInfo));
xhr.send(formData);
}
I followed the instructions here:
https://www.tiny.cloud/docs/general-configuration-guide/upload-images/#imageuploaderoptions
The other tutorial I utilized (which is just about the same thing) is here:
https://www.codexworld.com/tinymce-upload-image-to-server-using-php/comment-page-1/#comment-61677
You can't use the variable name 'formData' to initialize to a constructor 'FormData', the variable name overrides the constructor definition. So it should be:
var FormRequest= new FormData();
But your variable CANNOT be named FormData. I just ran into this in a Vue app.
If you've change the name and still getting the same error, perhaps it's caching the old page. If using chrome or fitefox you should be able to add a breakpoint in that function and step to the exact line with the error.
Everything looks right with the code

AJAX POST request with response

As the title states, I'm looking to make a POST request using JavaScript and also get a response. Here's my current code:
var request = new XMLHttpRequest();
request.open('POST', 'test.php', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success
console.log(request.responseText)
} else {
// Server-side Error
console.log("Server-side Error")
}
};
request.onerror = function() {
// Connection Error
console.log("Connection Error")
};
request.send({
'color':'red',
'food': 'carrot',
'animal': 'crow'
});
With test.php being:
<?php
echo $_POST['color'];
?>
This should return 'red' but instead returns nothing.
This seems like a simple problem but I could only find solutions for people using jQuery. I'd like a solution that does not rely on and libraries.
The send method takes a string rather than an object, perhaps more like:
var request = new XMLHttpRequest();
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
console.log(request.response)
} else {
console.log("Server-side Error")
}
};
request.onerror = function() {
console.log("Connection Error")
};
request.open('POST', 'test.php', true);
request.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
request.send('color=red&food=carrot&animal=crow');
The JavaScript problem
You are trying to send a generic Object, so it gets converted to a String ("[Object object]"), and the data is lost.
Convert the data to a FormData object instead.
var data = {
'color':'red',
'food': 'carrot',
'animal': 'crow'
};
var formData = new FormData();
Object.keys(data).forEach(function (key) {
formData.append(key, data[key]);
})
request.send(formData);
The PHP problem
All of the current solutions simply log the source code of "test.php" to the console as opposed to logging 'red' to the console
This is an issue unrelated to your code. It is also a FAQ. See: PHP code is not being executed, instead code shows on the page

Symfony 3 - Sending AJAX request as XmlHttpRequest() (javascript) does not pick up request as XmlHttpRequest in backend

I have an ExceptionListener implemented in Symfony3 (also works in Symfony2). The ExceptionListener identifies whether the request was normal HTTP or AJAX (XmlHttpRequest) and generates a response accordingly. When using jQuery .post() or .ajax(), the ExceptionListener returns $request->isXmlHttpRequest() as TRUE, but when using javascript var xhr = new XmlHTTPRequest(), the ExceptionListener returns $request->isXmlHttpRequest() as FALSE. I am using the latter in a small amount of instances where files need to be uploaded via AJAX (which cannot be done using .post() or .ajax().
I am looking for a solution (either frontend or backend) to resolve my ExceptionListener incorrectly picking this up as a normal HTTP request.
Frontend Code:
function saveUser()
{
var form = document.getElementById('userForm');
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open('POST', '{{url('saveUser')}}', true);
xhr.onreadystatechange = function (node)
{
if (xhr.readyState === 4)
{
if (xhr.status === 200)
{
var data = JSON.parse(xhr.responseText);
if (typeof(data.error) != 'undefined')
{
$('#processing').modal('hide');
$('#errorMsg').html(data.error);
$('#pageError').modal('show');
}
else
{
$('#successMsg').html('User Successfully Saved');
$('#processing').modal('hide');
$('#pageSuccess').modal('show');
$('#userModal').modal('hide');
updateTable();
}
}
else
{
console.log("Error", xhr.statusText);
}
}
};
$('#processing').modal('show');
xhr.send(formData);
return false;
}
ExceptionListener.php (partial)
# If AJAX request, do not show error page.
if ($request->isXmlHttpRequest()) # THIS RETURNS FALSE ON JS XmlHTTPRequest()
{
$response = new Response(json_encode(array('error' => 'An internal server error has occured. Our development team has been notified and will investigate this issue as a matter of priority.')));
}
else
{
$response = new Response($templating->render('Exceptions/error500.html.twig', array()));
}
When using vanilla ajax you need to pass the following header to your ajax request
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

Categories

Resources