大家可能以前用ajax上傳文件時,是把form提交到<iframe></iframe>,HTML代碼如下:
- <form action="uploadAction.action" enctype="multipart/form-data" id="fileform" name="fileform" method="post"
- target="upload-target">
- <input type="file" value="瀏覽" name="upload" />
- <input type="submit" value="提交"/>
- </form>
- <iframe id="upload-target"></iframe>
<form action="uploadAction.action" enctype="multipart/form-data" id="fileform" name="fileform" method="post"
target="upload-target">
<input type="file" value="瀏覽" name="upload" />
<input type="submit" value="提交"/>
</form>
<iframe id="upload-target"></iframe>
這樣不用跳轉頁面就可以實現文件的上傳,Action的代碼如下:
- public class UploadAction extends ActionSupport {
- //上傳的文件
- private File upload;
- //上傳文件的類型
- private String uploadContentType;
- 上傳文件的文件名
- private String uploadFileName;
- //getter setter
- @Override
- public String execute() throws Exception {
- System.out.println(upload.length());
- FileOutputStream fos = new FileOutputStream(ServletActionContext.getServletContext().getRealPath("/") + uploadFileName);
- FileInputStream fis = new FileInputStream(upload);
- byte[] buffer = new byte[10240];
- int len = 0;
- double temp = 0;
- int total = fis.available();
- while((len = fis.read(buffer)) > 0){
- fos.write(buffer, 0, len);
- fos.flush();
- }
- fis.close();
- fos.close();
- return SUCCESS;
- }
public class UploadAction extends ActionSupport {
//上傳的文件
private File upload;
//上傳文件的類型
private String uploadContentType;
上傳文件的文件名
private String uploadFileName;
//getter setter
@Override
public String execute() throws Exception {
System.out.println(upload.length());
FileOutputStream fos = new FileOutputStream(ServletActionContext.getServletContext().getRealPath("/") + uploadFileName);
FileInputStream fis = new FileInputStream(upload);
byte[] buffer = new byte[10240];
int len = 0;
double temp = 0;
int total = fis.available();
while((len = fis.read(buffer)) > 0){
fos.write(buffer, 0, len);
fos.flush();
}
fis.close();
fos.close();
return SUCCESS;
}
這樣就可以在一個頁面上上傳文件了。但怎麼顯示上傳文件的進度呢。一開始我的想法是在Action增加一個perc屬性,該屬性存放着上傳的進度,再增加一個方法,輸出perc的值.
- private double perc;
- blic String ajaxGetPerc() throws Exception{
- HttpServletResponse response = ServletActionContext.getResponse();
- PrintWriter writer = null;
- writer = response.getWriter();
- writer.println(perc);
- writer.flush();
- writer.close();
- return null;
private double perc;
public String ajaxGetPerc() throws Exception{
HttpServletResponse response = ServletActionContext.getResponse();
PrintWriter writer = null;
writer = response.getWriter();
writer.println(perc);
writer.flush();
writer.close();
return null;
}
最後試驗了一下,發現該方法行不通,能上傳文件,使用ajax返回的進度值始終是0;
想想第二種方法,使用線程的方式上傳文件,並把進度值保存在session中, 並且要使用兩個頁面,一個頁面負責文件的上傳,一個負責顯示進度。詳細代碼如下:
upload.jsp負責文件的上傳,是一個很普通的HTML頁面
- <body>
- <h1>文件上傳</h1>
- <form action="uploadAction.action" enctype="multipart/form-data" id="fileform" name="fileform" method="post"
- >
- <input type="file" value="瀏覽" name="upload" />
- <input type="submit" value="提交"/>
- </form>
- </body>
<body>
<h1>文件上傳</h1>
<form action="uploadAction.action" enctype="multipart/form-data" id="fileform" name="fileform" method="post"
>
<input type="file" value="瀏覽" name="upload" />
<input type="submit" value="提交"/>
</form>
</body>
showPerc.jsp使用ajax間隔的查詢進度值
- <?xml version="1.0" encoding="UTF-8" ?>
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <script type="text/javascript" src="<%=path %>/js/jquery-1.3.2.min.js"></script>
- <script type="text/javascript">
- var xmlHttp ;
- function createXMLHttp(){
- if(window.ActiveXObject){
- xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
- }
- else{
- xmlHttp = new XMLHttpRequest() ;
- }
- }
- function ajaxSend(){
- createXMLHttp() ;
- var url ="<%=path %>/getUploadPerc.action?random=" + Math.random(); ;
- xmlHttp.onreadystatechange = handler ;
- xmlHttp.open("GET",url,true) ;
- //xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
- xmlHttp.send(null) ;
- }
- function handler(){
- if(xmlHttp.readyState == 4) {
- if(xmlHttp.status == 200) {
- var percent = xmlHttp.responseText ;
- document.getElementById('pre').innerHTML = percent;
- var t = setTimeout("ajaxSend()",100) ;
- if(percent == 100){
- alert('上傳完成');
- clearTimeout(t);
- }
- }
- }
- return true;
- }
- window.onload = function(){
- ajaxSend();
- }
- </script>
- <title>文件上傳</title>
- </head>
- <body>
- <h1>進度條</h1>
- <div id="pre"></div>
- </body>
- </html>
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="<%=path %>/js/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
var xmlHttp ;
function createXMLHttp(){
if(window.ActiveXObject){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else{
xmlHttp = new XMLHttpRequest() ;
}
}
function ajaxSend(){
createXMLHttp() ;
var url ="<%=path %>/getUploadPerc.action?random=" + Math.random(); ;
xmlHttp.onreadystatechange = handler ;
xmlHttp.open("GET",url,true) ;
//xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlHttp.send(null) ;
}
function handler(){
if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
var percent = xmlHttp.responseText ;
document.getElementById('pre').innerHTML = percent;
var t = setTimeout("ajaxSend()",100) ;
if(percent == 100){
alert('上傳完成');
clearTimeout(t);
}
}
}
return true;
}
window.onload = function(){
ajaxSend();
}
</script>
<title>文件上傳</title>
</head>
<body>
<h1>進度條</h1>
<div id="pre"></div>
</body>
</html>
Action代碼
- package com.struts.action;
- import java.io.*;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- public class UploadAction extends ActionSupport {
- private String title;
- private File upload;
- private String uploadContentType;
- private String uploadFileName;
- private String savePath;
- private double perc;
- public double getPerc() {
- return perc;
- }
- public void setPerc(double perc) {
- this.perc = perc;
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public File getUpload() {
- return upload;
- }
- public void setUpload(File upload) {
- this.upload = upload;
- }
- public String getUploadContentType() {
- return uploadContentType;
- }
- public void setUploadContentType(String uploadContentType) {
- this.uploadContentType = uploadContentType;
- }
- public String getUploadFileName() {
- return uploadFileName;
- }
- public void setUploadFileName(String uploadFileName) {
- this.uploadFileName = uploadFileName;
- }
- public String getSavePath() {
- return savePath;
- }
- public void setSavePath(String savePath) {
- this.savePath = savePath;
- }
- @Override
- public String execute() throws Exception {
- System.out.println(upload.length());
- File toFile = new File(ServletActionContext.getServletContext().getRealPath("/") + uploadFileName);
- HttpSession session = ServletActionContext.getRequest().getSession();
- session.setAttribute("perc", 0);
- UploadThread uploadThread = new UploadThread(upload,toFile,session);
- Thread thread = new Thread(uploadThread);
- thread.start();
- return SUCCESS;
- }
- public String ajaxGetPerc() throws Exception{
- HttpSession session = ServletActionContext.getRequest().getSession();
- System.out.println("session perc------" + session.getAttribute("perc"));
- //ServletActionContext.getResponse().getOutputStream().println((String)session.getAttribute("perc"));
- HttpServletResponse response = ServletActionContext.getResponse();
- PrintWriter writer = null;
- writer = response.getWriter();
- int perc = (Integer)session.getAttribute("perc");
- writer.println(perc);
- writer.flush();
- writer.close();
- return null;
- }
- }
- /**
- *
- *
- * 因爲原本文件上傳完才能跳轉,故在一個線程中上傳文件,加速跳轉到showPerc.jsp去顯示進度.
- *
- */
- class UploadThread implements Runnable {
- //在當前線程中上傳的文件.
- private File from ;
- //保存到服務器硬盤上的位置.
- private File to ;
- //HttpSession需要傳遞過來,直接以ServletActionContext.getRequest.getSession將會拋出NullPointerException.
- private HttpSession httpSession;
- //構造方法,用來傳址.
- public UploadThread(File from, File to , HttpSession httpSession) {
- this.from = from;
- this.to = to;
- this.httpSession = httpSession;
- }
- //線程中處理上傳.
- @Override
- public void run() {
- copy(from, to , httpSession);
- }
- //自己實現的上傳方法,因爲需要計算進度,所以無法使用IOUtils.copy(InputStream in , OutputStream out)方法了.
- /**
- * @param from 需要上傳的文件.
- * @param to 保存到服務器上的位置.
- * @param httpSession 得到當前窗口的session.
- */
- public void copy(File from, File uploadFile , HttpSession httpSession) {
- InputStream fis;
- try {
- fis = new FileInputStream(from);
- OutputStream fos = new FileOutputStream(uploadFile);
- byte[] buffer = new byte[10240];
- int len = 0;
- double temp = 0;
- int perc = 0;
- int total = fis.available();
- while((len = fis.read(buffer)) > 0){
- fos.write(buffer, 0, len);
- fos.flush();
- temp += len;
- perc = (int)(temp / total * 100);
- //System.out.println(perc + "----------------" + total);
- httpSession.setAttribute("perc", perc);
- Thread.sleep(200);
- }
- fis.close();
- fos.close();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
package com.struts.action;
import java.io.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class UploadAction extends ActionSupport {
private String title;
private File upload;
private String uploadContentType;
private String uploadFileName;
private String savePath;
private double perc;
public double getPerc() {
return perc;
}
public void setPerc(double perc) {
this.perc = perc;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public File getUpload() {
return upload;
}
public void setUpload(File upload) {
this.upload = upload;
}
public String getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
public String getSavePath() {
return savePath;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
@Override
public String execute() throws Exception {
System.out.println(upload.length());
File toFile = new File(ServletActionContext.getServletContext().getRealPath("/") + uploadFileName);
HttpSession session = ServletActionContext.getRequest().getSession();
session.setAttribute("perc", 0);
UploadThread uploadThread = new UploadThread(upload,toFile,session);
Thread thread = new Thread(uploadThread);
thread.start();
return SUCCESS;
}
public String ajaxGetPerc() throws Exception{
HttpSession session = ServletActionContext.getRequest().getSession();
System.out.println("session perc------" + session.getAttribute("perc"));
//ServletActionContext.getResponse().getOutputStream().println((String)session.getAttribute("perc"));
HttpServletResponse response = ServletActionContext.getResponse();
PrintWriter writer = null;
writer = response.getWriter();
int perc = (Integer)session.getAttribute("perc");
writer.println(perc);
writer.flush();
writer.close();
return null;
}
}
/**
*
*
* 因爲原本文件上傳完才能跳轉,故在一個線程中上傳文件,加速跳轉到showPerc.jsp去顯示進度.
*
*/
class UploadThread implements Runnable {
//在當前線程中上傳的文件.
private File from ;
//保存到服務器硬盤上的位置.
private File to ;
//HttpSession需要傳遞過來,直接以ServletActionContext.getRequest.getSession將會拋出NullPointerException.
private HttpSession httpSession;
//構造方法,用來傳址.
public UploadThread(File from, File to , HttpSession httpSession) {
this.from = from;
this.to = to;
this.httpSession = httpSession;
}
//線程中處理上傳.
@Override
public void run() {
copy(from, to , httpSession);
}
//自己實現的上傳方法,因爲需要計算進度,所以無法使用IOUtils.copy(InputStream in , OutputStream out)方法了.
/**
* @param from 需要上傳的文件.
* @param to 保存到服務器上的位置.
* @param httpSession 得到當前窗口的session.
*/
public void copy(File from, File uploadFile , HttpSession httpSession) {
InputStream fis;
try {
fis = new FileInputStream(from);
OutputStream fos = new FileOutputStream(uploadFile);
byte[] buffer = new byte[10240];
int len = 0;
double temp = 0;
int perc = 0;
int total = fis.available();
while((len = fis.read(buffer)) > 0){
fos.write(buffer, 0, len);
fos.flush();
temp += len;
perc = (int)(temp / total * 100);
//System.out.println(perc + "----------------" + total);
httpSession.setAttribute("perc", perc);
Thread.sleep(200);
}
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
struts.xml配置文件
- <pre name="code" class="xml"> <action name="uploadAction" class="com.struts.action.UploadAction">
- <result>/showloadbar.jsp</result>
- <result name="input">/upload.jsp</result>
- <interceptor-ref name="fileUpload">
- <param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg</param>
- <param name="maximumSize">20000000000</param>
- </interceptor-ref>
- <interceptor-ref name="defaultStack"/>
- </action>
- <action name="getUploadPerc" class="com.struts.action.UploadAction" method="ajaxGetPerc">
- </action></pre>
- <action name="uploadAction" class="com.struts.action.UploadAction">
- <result>/showloadbar.jsp</result>
- <result name="input">/upload.jsp</result>
- <interceptor-ref name="fileUpload">
- <param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg</param>
- <param name="maximumSize">20000000000</param>
- </interceptor-ref>
- <interceptor-ref name="defaultStack"/>
- </action>
- <action name="getUploadPerc" class="com.struts.action.UploadAction" method="ajaxGetPerc">
- </action>
在這裏我設置只能上傳圖片文件.
可以上傳文件,並能顯示進度。但這裏使用session存取進度值,會加重服務器的負擔。各位有什麼好的方法可以告訴我。謝謝