I am taking an online course and one of the things we have to do is print out the JSON entries from localhost:8080/tasks. when i go to localhost:8080, it is supposed to run this code below. However, when i run it i get this response:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Dec 03 19:04:16 EST 2016
There was an unexpected error (type=Internal Server Error, status=500).
Exception parsing document: template="tasks", line 28 - column 42
column 42 is
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta charset="UTF-8" />
</head>
<body>
<h2>Tasks</h2>
<!-- TODO: add the ability to list tasks -->
<ul id="tasks">
</ul>
<form>
<input type="text" name="name" id="name"/>
<input type="button" onclick="addTask();" value="Add!"/>
</form>
<!-- the javascript has been embedded to the same site -->
<script th:inline="javascript">
// The URL to the application server that holds the tasks.
var url = "localhost:8080/tasks";
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
var response = JSON.parse(xmlHttp.responseText);
var liElement = document.createElement("li");
liElement.appendChild(document.createTextNode(response.name));
document.querySelector("#tasks").appendChild(liElement);
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
function loadTasks() {
}
function addTask() {
var name = document.querySelector("#name").value;
if (!name) {
return;
}
console.log(name);
var http = new XMLHttpRequest();
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/json");
var data = new Object();
data.name = name;
http.onreadystatechange = function () {
if (http.readyState === 4) {
if (http.status === 200) {
addTaskToList(JSON.parse(http.responseText));
}
}
}
http.send(JSON.stringify(data));
}
function addTaskToList(task) {
var liElement = document.createElement("li");
liElement.appendChild(document.createTextNode(task.name));
document.querySelector("#tasks").appendChild(liElement);
}
window.onload = function () {
loadTasks();
};
</script>
</body>
why is this happening?
Tasks:
package sec.domain;
import java.util.UUID;
public class Task {
private String id;
private String name;
public Task() {
this.id = UUID.randomUUID().toString();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Tasks controller:
package sec.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import sec.domain.Task;
#RestController
#RequestMapping("/tasks")
public class TaskController {
private List<Task> tasks;
public TaskController() {
this.tasks = new ArrayList<>();
Task fixme = new Task();
fixme.setName("Fix me.");
this.tasks.add(fixme);
}
#RequestMapping(method = RequestMethod.GET)
public List<Task> list() {
return this.tasks;
}
#RequestMapping(method = RequestMethod.POST)
public Task add(#RequestBody Task task) {
this.tasks.add(task);
return task;
}
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public Task delete(#PathVariable String id) {
Task t = this.tasks.stream().filter(task -> task.getId().equals(id)).findFirst().get();
this.tasks.remove(t);
return t;
}
}
Thymeleaf requires valid XML, and on the line you posted you have:
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
The & isn't a valid XML character, so you need to either surround your javascript with CDATA like this:
<script>
// <![CDATA[
... javascript here ...
// ]]>
</script>
Or else replace them with &&
Looks like you missed ';' at the end of
http.onreadystatechange = function () {
if (http.readyState === 4) {
if (http.status === 200) {
addTaskToList(JSON.parse(http.responseText));
}
}
}
Related
I have a .cshtml file which contains JavaScript function to perform a POST action to my controller class.
<input type="text" placeholder="Username" id="username" />
<button type="submit" onclick="sendResult()">Submit</button>
<script type="text/javascript">
function sendResult() {
let username = document.getElementById('username').value;
try {
let xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "/Test/Test");
xmlhttp.setRequestHeader('Content-Type', 'text/html');
let xml = `<?xml version="1.0"?><query><Username>${username}</Username></query>`;
console.log(xml)
xmlhttp.send(xml);
let xmlResponse;
xmlhttp.onreadystatechange = async function () {
if (xmlhttp.readyState === XMLHttpRequest.DONE && xmlhttp.status === 200) {
xmlResponse = await xmlhttp.responseXML;
console.log(xmlResponse)
}
}
} catch (error) {
console.log(error)
}
}
</script>
In my controller class, I did not manage to receive the xml string (myXML) after clicking on the submit button. Why is that so?
// TestController.cs
public ActionResult Test()
{
return View();
}
[HttpPost]
public ActionResult Test(string myXML)
{
Service1Client o = new Service1Client();
o.Test(myXML);
return View();
}
This is my controller.
[HttpGet("GetFile")]
[Authorize]
public async Task<FileContentResult> GetFile([FromQuery] Guid fileId)
{
var fileName = string.Format("{0}.doc", _service.GetFileNameFromId(fileId));
var fileName = "someFile.doc";
var mimeType = "application/msword";
byte[] fileBytes = _service.GetFileByteArray(fileId);
System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
FileName = fileName,
Inline = false
};
Response.Headers.Add("Content-Disposition", cd.ToString());
return new FileContentResult(fileBytes, mimeType)
{
FileDownloadName = fileName
};
}
These are my response headers according to Swagger.
content-disposition: attachment; filename="someFile.doc"; filename*=UTF-8''someFile.doc
content-length: 3853
content-type: application/msword
date: Thu31 Mar 2022 13:05:34 GMT
server: Microsoft-IIS/10.0
x-powered-by: ASP.NET
But whenever I attempt to access the content-disposition header from Javascript, it returns null. I'm making an XMLHttpRequest.
var contentDisposition = this.getResponseHeader('content-disposition');
Does my server-side code have any issues that could be causing this?
Below is my work Post demo, you can refer to it.
FileAPIController.cs:
[Route("api/[controller]")]
[ApiController]
public class FileAPIController : ControllerBase
{
private IWebHostEnvironment webHostEnvironment;
public FileAPIController(IWebHostEnvironment _webHostEnvironment)
{
webHostEnvironment = _webHostEnvironment;
}
[HttpPost("UploadFile")]
public async Task<string> UploadFile([FromForm] IFormFile file)
{
string path = Path.Combine(this.webHostEnvironment.WebRootPath, "IFiles/", file.FileName);
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
FileName = file.FileName,
Inline = false
};
Response.Headers.Add("Content-Disposition", cd.ToString());
return "https://localhost:5001/IFiles/" + file.FileName;
}
}
Privacy.cshtml:
#{
ViewData["Title"] = "Privacy Policy";
}
<h1>#ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
<input type="file" id="File" />
<button id="AddButton" onclick="UploadFile()" type="submit">Add</button>
<script type="text/javascript">
function UploadFile() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "https://localhost:5001/api/FileAPI/UploadFile", true);
data = new FormData();
data.append("file", document.getElementById("File").files[0]);
xhttp.send(data);
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var disposition =xhttp.getResponseHeader('Content-Disposition');
alert(this.response);
}
};
}
</script>
Result:
I have set up a multiple file upload Form with jsp and ajax
here is my code
jsp
<%# page language="java" contentType="text/html; charset=cp1251"
pageEncoding="cp1251"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=cp1251">
<title>Загрузка файлов</title>
<link rel=stylesheet type="text/css" href="/styles/style.css">
<style>
.td {
valign: top
}
</style>
<script type="text/javascript">
function upload(){
var x = document.getElementById("plan_upload");
for (var i = 0; i < x.files.length; i++) {
var file = x.files[i];
var plan_type='${param.par_type}'
var formdata = new FormData();
formdata.append("plan_upload", file);
var ajax = new XMLHttpRequest();
ajax.cur_number=(i+1);
ajax.total_number=x.files.length;
ajax.addEventListener("error", errorHandlerPlanUpload, false);
ajax.addEventListener("abort", abortHandlerPlanUpload, false);
ajax.onreadystatechange = function (){
if (ajax.readyState==4 && ajax.status==200){
var total_number = ajax.total_number;
var cur_number= ajax.cur_number;
if(cur_number==total_number){
alert('Загрузка файлов успешно завершена!');// upload successfull
window.opener.location.reload()
window.close();
}
}
}
ajax.open("POST", "MultipleFileUpload?par_type="+plan_type);
ajax.send(formdata);
}
}
function updateList (){
var input = document.getElementById('plan_upload');
var output = document.getElementById('fileList');
output.innerHTML = '<ul>';
for (var i = 0; i < input.files.length; ++i) {
output.innerHTML += '<li>' + input.files.item(i).name + '</li>';
}
output.innerHTML += '</ul>';
}
function errorHandlerPlanUpload(event){
alert("Ошибка при загрузке файлов!"); //cancel
window.opener.location.reload();
window.close()
}
function abortHandlerPlanUpload(event){
alert("Загрузка файлов была отменена!");//abort
window.opener.location.reload();
window.close();
}
</script>
</head>
<body style="background-color: white;">
<form name="multiple_upload_form" enctype="multipart/form-data" autocomplete="off" onsubmit="return false;" >
<input onchange="updateList()" accept=".xml,.osf,.zsf,.plax" id="plan_upload" name="plan_upload" multiple type="file" required />
<br/>Выбранные файлы:
<div id="fileList"></div>
<button id="testt" onclick="upload()" type="submit">Загрузить файлы</button>
</form>
</body>
</html>
server side java
package com.ieml.servlets.plan;
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.*;
import org.apache.commons.fileupload.servlet.*;
import com.ieml.Global;
import com.ieml.util.*;
public class MultipleFileUploadServlet extends javax.servlet.http.HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
//PrintWriter out = response.getWriter();
String path = com.ieml.Global.getUploadDirectory();
Integer type= ServletUtilities.getIntParameter(request, "par_type");
if(path == null)
{
ServletUtilities.forwardErrorPage(request, response, "Не указано место хранения файлов");
return;
}
if(type==null)
{
ServletUtilities.forwardErrorPage(request, response, "Не указан тип плана");
return;
}
else
{
switch(type)
{
case 1:path+="/plans/incoming/"; break;
case 2:path+="/plansMag/incoming/";break;
case 3:path+="/plansSPO/incoming/";break;
default:break;
}
}
boolean isMultipart = ServletFileUpload.isMultipartContent(new ServletRequestContext(request));
if (isMultipart)
{
try
{
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
List<?> items = upload.parseRequest(request);
Iterator<?> iter = items.iterator();
while(iter.hasNext())
{
FileItem item = (FileItem)iter.next();
if (!item.isFormField())
{
String fileName = item.getName();
if(!fileName.endsWith(".xml") &&!fileName.endsWith(".XML") &&
!fileName.endsWith(".osf") && !fileName.endsWith(".OSF") &&
!fileName.endsWith(".zsf") && !fileName.endsWith(".ZSF")&&
!fileName.endsWith(".plax") && !fileName.endsWith(".PLAX")
)
{
ServletUtilities.forwardErrorPage(request, response, "Поддерживаемые форматы файлов: .xml, .osf, .zsf, .plax");
return;
}
try (Connection conn = Global.getConnection()){
File f = new File(path, fileName);
if(f.exists())
{
boolean success=f.delete();
if(!success)
{
try {
System.err.println("Не могу удалить файл "+f.getCanonicalPath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
File uploadedFile = new File(path, fileName);
try
{
item.write(uploadedFile);
}
catch(Exception e)
{
e.printStackTrace();
log(e.getMessage());
ServletUtilities.forwardErrorPage(request, response, "Не могу записать файл.");
}
}
break;
}
}
}
catch(SQLException e){
e.printStackTrace();
}
catch(FileUploadException fue){
fue.printStackTrace();
log(fue.getMessage());
ServletUtilities.forwardErrorPage(request, response, "Не могу принять файл.");
}
}
}
}
Due to the fact I have to use the old apache-commons file upload I decided to make several ajax calls (one for each file), but only display the "upload successfull" message after the last file has finished uploading.
For some reason sometimes browsers display more than one successfull
upload alert instead of just one
It seem to happen more if I have many(15-20) files selected for upload. Server side upload directory is currently local folder. Any suggestions how to fix the issue with my onreadystatechange function?
I'm using chrome 49.0.2623.112 m and firefox 52.1.1 on windows xp
UPD
fore some reason i always equals to the number of files
function upload(){
var x = document.getElementById("plan_upload");
var noOfFiles = x.files.length;
var i=0;
for (i = 0; i < noOfFiles; i++)
{
var file = x.files[i];
var plan_type='${param.par_type}'
var formdata = new FormData();
formdata.append("plan_upload", file);
var ajax = new XMLHttpRequest();
ajax.cur_number=(i+1);
ajax.total_number=x.files.length;
ajax.addEventListener("error", errorHandlerPlanUpload, false);
ajax.addEventListener("abort", abortHandlerPlanUpload, false);
ajax.onreadystatechange = function ()
{
if (ajax.readyState==4 && ajax.status==200)
{
var total_number = ajax.total_number;
var cur_number= ajax.cur_number;
alert('i= '+i+' total files '+noOfFiles ) // i always equals noOfFiles
if(i == noOfFiles-1){ //Check if last file
alert('Загрузка файлов успешно завершена!');// upload successfull
window.opener.location.reload()
window.close();
}
}
}
ajax.open("POST", "MultipleFileUpload?par_type="+plan_type);
ajax.send(formdata);
}
}
If I understood your question correctly, you don't want to show alert on every file uploaded successfully. Instead you want to display only for last file.
If I'm not wrong you've to check one if condition for the alert statement and check if it's last but nothing file.
function upload(){
var x = document.getElementById("plan_upload");
var noOfFiles = x.files.length;
for (var i = 0; i < noOfFiles; i++)
{
var file = x.files[i];
var plan_type='${param.par_type}'
var formdata = new FormData();
formdata.append("plan_upload", file);
var ajax = new XMLHttpRequest();
ajax.cur_number=(i+1);
ajax.total_number=x.files.length;
ajax.addEventListener("error", errorHandlerPlanUpload, false);
ajax.addEventListener("abort", abortHandlerPlanUpload, false);
ajax.onreadystatechange = function ()
{
if (ajax.readyState==4 && ajax.status==200)
{
var total_number = ajax.total_number;
var cur_number= ajax.cur_number;
if(cur_number==total_number)
{
if(i == noOfFiles-1){ //Check if last file
alert('Загрузка файлов успешно завершена!');// upload successfull
}
window.opener.location.reload()
window.close();
}
}
}
ajax.open("POST", "MultipleFileUpload?par_type="+plan_type);
ajax.send(formdata);
}
}
You can find small piece of working code. Hope this helps.
Cheers..!
I solved the issue by my AJAX calls synchronous by passing additional false argument to the open function of the XMLHttpRequest
function upload()
{
var x = document.getElementById("plan_upload");
var numOfFiles= x.files.length;
for (var i = 0; i < numOfFiles; i++)
{
var file = x.files[i];
var plan_type='${param.par_type}'
var formdata = new FormData();
formdata.append("plan_upload", file);
var ajax = new XMLHttpRequest();
ajax.addEventListener("error", errorHandlerPlanUpload, false);
ajax.addEventListener("abort", abortHandlerPlanUpload, false);
ajax.onreadystatechange = function ()
{
if (ajax.readyState==4 && ajax.status==200)
{
if(i== numOfFiles-1)
{
alert('Загрузка файлов успешно завершена!');
window.opener.location.reload()
window.close();
}
}
}
ajax.open("POST", "MultipleFileUpload?par_type="+plan_type,false);
ajax.send(formdata);
}
}
i'm trying to send data from a view to a controller using POST but i doesn't seems to work.
Here's my code (javascript function) :
function showHint(str) {
if (str.length == 0) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
}
};
var titre = str;
xmlhttp.open("POST", "CheckReturn", true);
//xmlhttp.send(titre);
xmlhttp.send({"titre":titre});
}
}
the html triggering it :
<div id="check-name" class="form-row">
<input id="name" type="text" name="name" placeholder="Titre de l'événement" onkeyup="showHint(this.value)">
<span id="txtHint"></span>
</div>
and finally, the controller SUPPOSED to get it :
[HttpPost]
public ActionResult CheckReturn(string titre)
{
var contexte = new intranetEntities();
var ajax = contexte.evenementiel.SqlQuery("Somequery" + titre);
ViewBag.ajax = ajax;
return PartialView();
}
i checked bit firebug, the data is sent, but with visual studio's debugger, i see that "titre" always stay null.
What can i do ?
I've run into something similar in the past with asp.net but I never really tried to understand what's happening. What fixed it for me was the following:
make a new class somewhere in your back-end (anywhere, doesn't matter for now)
class TitreWrapper {
public string titre {get; set;}
}
then in your controller
[HttpPost]
public ActionResult CheckReturn(TitreWrapper titreWrap)
{
string titre = titreWrap.titre;
}
this should work according to my previous experience
the top answer is wrong (but right in other circumstances I think)
for this problem the following worked:
xmlhttp.open("POST", "/CheckReturn?titre=" + titre, true);
and then just
xmlhttp.send();
OR
xmlhttp.open("POST", "CheckReturn", true);
then
xmlhttp.send("titre=" + titre);
Hi i have a requirement in which i have to check something from struts action class and then send the result back to the browser using ajax call called in a JS fx'.The issue is im not able to hit the action class and console is throwing the following error:
org.apache.struts.action.RequestProcessor processActionCreate No action instance for path /ChangePwdAjax could be created
java.lang.ClassNotFoundException:test.ChangePwdAjaxAction.java
The class is compiled and the package context is valid test.ChangePwdAjaxAction.java
Any ideas what and where im doing it wrong?
Here is what i have written so far.
JS code
function checkError()
{
var valuePassword="test";
var url = "/test/ChangePwdAjax.do?newPass="+valuePassword;
var xmlHTTP = getXMLHTTPRequest();
xmlHTTP.onreadystatechange = function() {
handleResponse(xmlHTTP); }
xmlHTTP.open("GET",url,true);
xmlHTTP.send();
}
function handleResponse(xmlHTTP){
alert("handleResponse");
if (xmlHTTP.readyState == 4 && xmlHTTP.status == 200) {
alert("handleResponse");
var xmlDoc = xmlHTTP.responseXML;
alert(xmlDoc.documentElement.getElementsByTagName("pwdFlag")[0].text);
}
}
function getXMLHTTPRequest(){
alert("getXMLHTTPRequest");
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
else{
alert("XMLHttpRequest is not supported!");
}
}
Action class code
public class ChangePwdAjaxAction extends Action {
public ActionForward execute(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request,final HttpServletResponse response)
{
System.out.println("----IN--AJAX ACTION----------");
final HttpSession session= request.getSession(false);
if(session==null || session.getAttribute("user_id")==null){
return mapping.findForward("sessionexpired");
}
final String user_id=(String)session.getAttribute("user_id");
try{
final BusinessDelegate busdel=new BusinessDelegate(user_id,session.getId());
String newpwd = (String)request.getParameter("newPass");
boolean b=busdel.checkOldPWd(user_id, newpwd);
//checking return values from bus delegate
response.setContentType("text/xml");
PrintWriter printwriter = response.getWriter();
printwriter.println("<?xml version=\"1.0\"?>");
printwriter.println("<Root>");
if(b)
{
System.err.println("----New password Failed--Y--------");
printwriter.println("<pwdFlag>"+"Y"+"</pwdFlag>");
}
else
{
System.out.println("----New password OK---N-------");
printwriter.println("<pwdFlag>"+"N"+"</pwdFlag>");
}
printwriter.println("</Root>");
}catch(Exception e){
logger.logCommon("Login Action : Login Process in Action : ", "EXCEPTION");
logger.logError(e);
}
return null;
}
}
Struts-config entry
<action path="/ChangePwdAjax" type="test.ChangePwdAjaxAction.java"/>
OOps this had to be
action path="/ChangePwdAjax" type="test.ChangePwdAjaxAction"/>
rather than
action path="/ChangePwdAjax" type="test.ChangePwdAjaxAction.java"/>