ajax multiple file upload alert after last file has finished - javascript

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);
}
}

Related

upload image to node js server + javascript and display in the same page with ajax jquery

I need to upload a image(jpg||png||jpeg) to the server I created with node js.
I have the router and the requestHandlers.. that redirect to this function:
function reqUpload(request, response) {
var form = new formidable.IncomingForm();
form.parse(request, function (error, fields, files) {
lastFileUploaded=files.up.originalFilename;
if (files.up.originalFilename.match(/\.(jpg|jpeg|png)$/i)) {
//check if alredy exists
fs.access(files.up.originalFilename, fs.F_OK, (err) => {
if (err) {
fs.rename(files.up.filepath, files.up.originalFilename, function (err) {
if (err) {
fs.unlink(files.up.originalFilename);
fs.rename(files.up.filepath, files.up.originalFilename);
}
var data;
fs.readFile('./html/std.html', 'utf8', function (err, data) {
if (err) {
console.error(err);
return
}
response.writeHead(200, { "Content-Type": "text/html" });
response.write(data);
response.end();
});
})
}else{
console.log("Already exists, replacing it!");
fs.rename(files.up.filepath, files.up.originalFilename, function (err) {
if (err) {
fs.unlink(files.up.originalFilename);
fs.rename(files.up.filepath, files.up.originalFilename);
}
})}
});
} else {
console.log("format not accepted! try again.");
}
This is working if I upload my file via a button and the form action ="/reqUpload"
however, I need to load in the same page.
How do I do it with ajax + jquery?
I need to display the image uploaded in the same page I uploaded it, without refreshing the page.
I have this function:
function loadPhoto(e){
alert("entered")
var xhr = new XMLHttpRequest();
xhr.open('POST', '/reqUpload');
xhr.onload = function(){
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
alert(this.responseText)
document.getElementById('#photo').innerHTML = this.responseText;
}
xhr.send('/html/std.html');
e.preventDefault();
}
but it breaks and returns this:
enter image description here
seems not to send the file in the correct format, or smth like that
This resolved my case
function loadPhoto(e){
e.preventDefault();
//forming images
var formData = new FormData( document.getElementById("uploading") );
for(var i = 0; i < document.getElementById("up").files.length; i++) {
console.log(i)
formData.append("up[]",document.getElementById("up").files[i]);
}
var filename = document.getElementById('up');
alert(filename)
filename = filename.files[0].name;
alert(filename)
var xhr = new XMLHttpRequest();
xhr.open('POST', '/reqUpload');
xhr.onload = function(){
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
alert(this.responseText)
document.getElementById('#photo').innerHTML = this.responseText;
}
xhr.send(formData);
}

How to and retrieving JSON data from a server

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));
}
}
}

How can i output this content to a textarea?

I have tried to pass on the text from a php page into my html page, as described by Chris Bakers answer (javascript, not jquery).
Call php function from javascript
The code works, if i use the normal text (id=output), but i would like to output the text to a textarea (id=text1) instead of a normal text, just changing the id does not work.
This is my code:
<html>
<head>
</head>
<body>
<textarea id="text1" style="background-color: #969696" cols="50" rows="10" readonly></textarea>
<div id="output">waiting for action</div>
</body>
<script>
function getOutput() {
var value = document.getElementById("artikelnr").value;
var file = selectedValue()+".csv";
getRequest(
"verarbeitung.php?eingabe="+value+"&eingabe2="+file, // URL for the PHP file
drawOutput, // handle successful request
drawError // handle error
);
return false;
}
// handles drawing an error message
function drawError() {
var container = document.getElementById('text1');
container.innerHTML = 'Bummer: there was an error!';
}
// handles the response, adds the html
function drawOutput(responseText) {
var container = document.getElementById('text1');
container.innerHTML = responseText;
}
// helper function for cross-browser request object
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
} catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function(){
if(req.readyState == 4) {
return req.status === 200 ?
success(req.responseText) : error(req.status);
}
}
req.open("GET", url, true);
req.send(null);
return req;
}
</script>
</html>
Because you should use .value instead of .innerHTML.
Reference: JavaScript get TextArea input via .value or .innerHTML?
It is not setInnerHtml, textarea has a value attribute. Not really logical but well...
mad you a fiddle:
document.getElementById("bla").value = "test";
<textarea id="bla" readonly >Initial Value</textarea>

XMLHttpRequest error SCRIPT10

Hi all I have to connect to an external server to retrieve data.
They told me to use their script and I have to modify something because it was wrong. Now I ahve a problem when I try to lunch my request.
Return me an error into my internet explorer console
SCRIPT10: The data required for the completion of this operation are
not yet available.
This is my javascript page, the problem I think is because the query doesn't finish in time to print my result. How can I print the result when they are ready and don't return me error?
I have try to comment all my request and leave only the method "open" but the error return me every time. Why??
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript">
var req = null ;
function sendRequest(){
var urlStr="www.test.it";
var xmlString="";
xmlString+="<?xml version='1.0' encoding='UTF-8'?><some xml>";
createHTTPRequestObject();
var resp = getResponseText(urlStr+"?"+xmlString,null);
var xmlDoc;
xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
xmlDoc.async = false;
xmlDoc.loadXML(resp);
alert(xmlDoc.xml);
}
function createHTTPRequestObject(){
req=null ;
var pXmlreq = false ;
if (window.XMLHttpRequest) {
pXmlreq = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
try{
pXmlreq = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e1) {
try{
pXmlreq = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e2) {
}
}
}
req = pXmlreq ;
}
function getResponseText(action,query,method,async,contenttype){
if(method==null){
method="POST";
}
if(async==null){
async="true";
}
if(contenttype==null){
contenttype = "application/x-www-form-urlencoded";
}
req.open(method,action, async);
req.setRequestHeader("Content-Type", contenttype);
if(query){
req.send(query);
}else{
req.send();
}
return req.responseText ;
}
</script>
</head>
<body>
<input type="button" name="Request" value="Request" onclick="sendRequest();"/>
<div id="content" />
</body>
</html>
You are trying to read the responseText before it is ready. Looks like you are treating a asynchronous call as synchronous. That would be the issue.

AJAX call to struts action not working

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"/>

Categories

Resources