java基於servlet完成文件上傳功效解析。本站提示廣大學習愛好者:(java基於servlet完成文件上傳功效解析)文章只能為提供參考,不一定能成為您想要的結果。以下是java基於servlet完成文件上傳功效解析正文
比來項目須要做一個文件上傳功效,做完了分享下,順帶當作筆記。
上傳功效用後台用java完成,前端重要是js的ajax完成。後台還參加准時刪除暫時文件。
後果如圖
起首是上傳功效的重要類,上面是代碼
package util.upload;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = -3100028422371321159L;
private boolean isAllowed;
private String upFileName;
//界說正當後綴名的數組
private String[] allowedExtName=new String[]
{"zip","rar",//緊縮文件
"txt","doc","wps","docx","java",//文本
"xls","xlsx",//表格
"ppt","pptx",//幻燈片
"pdf",//pdf
"jpg","jpeg","bmp","gif","png"//圖片
};
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設置編碼格局為utf-8
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//獲得session,保留進度和上傳成果,上傳開端為nok,當為Ok表現上傳完成
HttpSession session=request.getSession();
session.setAttribute("result", "nok");
session.setAttribute("error", "");
String error="";
upFileName="";
isAllowed=false;
//給上傳的文件設一個最年夜值,這裡是不得跨越100MB
int maxSize=100*1024*1024;
//創立工場對象和文件上傳對象
DiskFileItemFactory factory=new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(factory);
//創立上傳監聽器和設置監聽器
UploadListener listener=new UploadListener();
session.setAttribute("LISTENER", listener);
upload.setProgressListener(listener);
//上傳途徑
String path = request.getSession().getServletContext().getRealPath("/upload");
String requestPath = request.getSession().getServletContext().getContextPath()+"/upload";
File dirFile =new File(path); //System.out.println(request.getSession().getServletContext().getContextPath());
//假如文件夾不存在則創立
if (!dirFile .exists() && !dirFile .isDirectory())
{
dirFile .mkdir();
}
//依據日期創立文件夾,保留到對應日期的文件夾下
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
String subDirName=sdf.format(date);
File subDirFile=new File(path+"/"+subDirName);
if (!subDirFile .exists() && !subDirFile .isDirectory())
{
subDirFile .mkdir();
}
try {
//解析上傳要求
List<FileItem> items=upload.parseRequest(request);
Iterator<FileItem> itr=items.iterator();
while(itr.hasNext()){
FileItem item=(FileItem)itr.next();
//斷定能否為文件域
if(!item.isFormField()){ if(item.getName()!=null&&!item.getName().equals("")){
//獲得上傳文件年夜小和文件稱號
long upFileSize=item.getSize();
String fileName=item.getName();
//獲得文件後綴名
String[] splitName=fileName.split("\\.");
String extName=splitName[splitName.length-1];
//檢討文件後綴名
for(String allowed:allowedExtName)
{
if(allowed.equalsIgnoreCase(extName))
{
isAllowed=true;
}
}
if(!isAllowed){
error="上傳文件格局不正當!";
break;
}
if(upFileSize>maxSize){
error="您上傳的文件太年夜了,請選擇不跨越100MB的文件!";
break;
}
//此時文件暫存在辦事器的內存中,結構暫時對象
File tempFile=new File(makeFileName(fileName));
//指定文件上傳辦事器的目次及文件稱號
File file=new File(path+"/"+subDirName+"/",tempFile.getName());
item.write(file);//第一種寫文件辦法
upFileName=requestPath+"/"+subDirName+"/"+tempFile.getName();
if(upFileName.equals("")){
error="沒選擇上傳文件!";
}
System.out.println(upFileName);
/*//結構輸出流讀文件 第二種寫文件辦法
InputStream is=item.getInputStream();
int length=0;
byte[] by=new byte[1024];
FileOutputStream fos=new FileOutputStream(file);
while((length=is.read(by))!=-1){
fos.write(by, 0, length);
//Thread.sleep(10);
}
fos.close();
//Thread.sleep(1000);*/
}else{
error="沒選擇上傳文件!";
}
}
}
} catch (Exception e) {
e.printStackTrace();
error="上傳文件湧現毛病:"+e.getMessage();
}
if(!error.equals("")){
System.out.println(error);
session.setAttribute("error", error);
}else{
session.setAttribute("result", "OK");
session.setAttribute("filename",upFileName);
}
}
/**
* 為避免文件籠罩的景象產生,要為上傳文件發生一個獨一的文件名
* @param filename 原文件名
* @return 生成的獨一文件名
*/
private String makeFileName(String filename){
return UUID.randomUUID().toString() + "_" + filename;
}
}
個中須要引入commons-fileupload-1.3.1.jar,commons-io-2.4.jar
上傳進程中,我們須要及時獲得上傳進度等信息,引入的庫裡為我們添加了一個ProgressListener接口,我們再寫一個類完成這個接口,下面類中添加該接口
//創立工場對象和文件上傳對象
DiskFileItemFactory factory=new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(factory);
//創立上傳監聽器和設置監聽器
UploadListener listener=new UploadListener();
session.setAttribute("LISTENER", listener);
upload.setProgressListener(listener);
上面是這個監聽類的詳細完成代碼
package util.upload;
import org.apache.commons.fileupload.ProgressListener;
public class UploadListener implements ProgressListener{
private volatile long
bytesRead = 0L,//上傳的字節數
contentLength = 0L,//總字節數
item = 0L;
public UploadListener()
{
super();
}
@Override
public void update(long aBytesRead, long aContentLength, int anItem) {
bytesRead = aBytesRead;
contentLength = aContentLength;
item = anItem;
}
public long getBytesRead()
{
return bytesRead;
}
public long getContentLength()
{
return contentLength;
}
public long getItem()
{
return item;
}
}
如今能獲得上傳進度等信息了,但還須要一個servlet前往給前端,上面完成
package util.upload;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.ProgressListener;
import com.谷歌.gson.Gson;
/**
獲得上傳進度,上傳途徑,毛病,上傳成果等信息
*/
public class GetProgressServlet extends HttpServlet{
private static final long serialVersionUID = -3596466520775012991L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
UploadListener listener= null;
HttpSession session = request.getSession();
String error=(String) session.getAttribute("error");
String result= (String) session.getAttribute("result");
String fileName=(String) session.getAttribute("filename");
PrintWriter out = response.getWriter();
long bytesRead = 0,contentLength = 0;
if (session != null)
{
listener = (UploadListener)session.getAttribute("LISTENER");
if (listener == null)
{
return;
}
else
{
bytesRead = listener.getBytesRead();//上傳的字節數
contentLength = listener.getContentLength();//總字節數
}
//本身界說的前往格局
String rp=bytesRead+","
+contentLength+","
+error+","
+result+","
+fileName;
//System.out.println(rp);
out.print(rp);
/* //前往json格局數據
Map<String,Object> map=new HashMap<String,Object>();
map.put("bytesRead", bytesRead);
map.put("contentLength", contentLength);
map.put("error", error);
map.put("result", result);
map.put("fileName", fileName);
Gson gson=new Gson();
String json=gson.toJson(map);
out.print(json);*/
out.flush();
out.close();
}
}
}
後台上傳的功效代碼寫完了,上面完成上傳的前端,起首是html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="js/upfile.js" charset="utf-8"></script>
<link rel="stylesheet" type="text/css" href="css/upfile.css">
</head>
<body >
<a href="javascript:addOne()">添加</a>
<div id="target">
<input type="file" id="file" name="file" onchange="addfile(event)" multiple/>
</div>
<span id="test">0</span>
</body>
</html>
界面比擬簡略,就一個添加的a標簽,擔任上傳的input隱蔽起來
css文件重要襯著的上傳進度的顯示
#file {
display: none;
}
.pro{
width:500px;
}
.pborder {
position: relative;
width: 500px; /* 寬度 */
border: 1px solid #B1D632;
padding: 1px;
}
.drawpro {
width: 0px;
display: block;
position: relative;
background: #B1D632;
color: #333333;
height: 20px; /* 高度 */
line-height: 20px; /* 必需和高度分歧,文本能力垂直居中 */
}
.pspan {
position: absolute;
width: 500px;
text-align: center;
font-weight: bold;
}
接著是前真個重點,js文件
//顯示上傳信息的html
var upfile_html = '<div class="pborder"><div class="drawpro">'
+ '<span class="pspan">0%</span></div></div><span name="path"></span><img src="common/upload/images/del.png" width="20" height="20" name="del" onclick=abortUpload(this)>';
var targetDIV_id = "target";//顯示上傳文件的目的div的ID
var httpXML = null;//發奉上傳要求的XMLHttpRequest對象
var httpProgress = null;//發送要求進度信息的XMLHttpRequest對象
var oldFileList = new Array();//修正時保留已有附件信息的列表
var uplist = new Array();//保留上傳文件的列表
var f_input;//上傳文件的input對象
var flag = true;//能否可以上傳下一個文件標記
var uurl = "Upload";//上傳文件的要求url
var gurl = "getProgress";//獲得上傳進度信息的url
var cancelFlag = 0;//撤消標記
var timer, waittimer;//准時器
var nowID = 0;//正在上傳文件的id
var ID = 0;//隊列中最初一個文件的id
/**
* 文件對象
*/
function UploadFile(id, file) {
this.id = id;
this.file = file;
this.state = 0;
this.path = "";
}
/**
* 初始化的辦法
*/
window.onload = function init() {
f_input = document.getElementById("file");
var tdiv = document.getElementById(targetDIV_id);
var oldspan = tdiv.getElementsByTagName("SPAN");
for ( var i = 0; i < oldspan.length; i++) {
oldFileList.push(oldspan[i].getAttribute("name"));
}
}
/**
* 選擇一個文件上傳
*/
function addOne() {
f_input.value = null;
f_input.click();
}
/**
* 選中文件後將文件對象添加到隊列,開端上傳
*
*/
function addfile(evt) {
var f = f_input.files[0];
if (f != undefined) {
var uf = new UploadFile(ID, f);
uplist.push(uf);
var div = document.createElement("DIV");
div.setAttribute("id", "pro" + (ID));
div.setAttribute("class", "pro");
div.innerHTML = upfile_html;
var targetDiv = document.getElementById(targetDIV_id);
targetDiv.appendChild(div);
div.getElementsByTagName("SPAN")[1].innerHTML = "文件名:"
+ uplist[ID].file.name;
waittimer = setInterval("upload()", 1000);
ID++;
}
}
/**
* 將隊列中的文件上傳
*/
function upload() {
if (flag == true) {
if (uplist.length > 0) {
var uf;
for ( var i = 0; i < uplist.length; i++) {
if (uplist[i].state == 0) {
uf = uplist[i];
uplist[i].state = 1;
break;
}
}
if (uf != undefined & uf != null) {
flag = false;
if (window.XMLHttpRequest) {
httpUP = new XMLHttpRequest();
} else if (window.ActiveXObject) {
httpUP = new ActiveXObject("Microsoft.XMLHTTP");
}
var formData = new FormData();
formData.append("file", uf.file);
httpUP.open("POST", uurl, true);
httpUP.upload.addEventListener('progress', uploadProgress, false);
httpUP.send(formData);
nowID = uf.id;
timer = setInterval("getP()", 50);
}
}
}
}
/**
* 獲得上傳進度等信息
*/
function getP() {
if (window.XMLHttpRequest) {
httpProgress = new XMLHttpRequest();
} else if (window.ActiveXObject) {
httpProgress = new ActiveXObject("Microsoft.XMLHTTP");
}
httpProgress.onreadystatechange = onProgress;
httpProgress.open("post", gurl, true);
httpProgress.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
httpProgress.send("&timeStamp=" + (new Date()).getTime());
}
/**
* 處置前往的上傳信息,顯示到界面
*/
function onProgress() {
if (httpProgress.readyState == 4 && httpProgress.status == 200) {
result = httpProgress.responseText;
var result = result.replace(/(^\s*)|(\s*$)/g, "");
var res = result.split(",");
var now = parseInt(res[0]);
var all = parseInt(res[1]);
var err = res[2];
var state = res[3];
var path = res[4];
var per = (now / all * 100).toFixed(2);
var prodiv = document.getElementById("pro" + nowID);
if (prodiv != null & prodiv != undefined) {
if (err != "" & err != null & err.length > 0) {
window.clearInterval(timer);
if (cancelFlag == 1) {
err = "上傳終止";
cancelFlag = 0;
}
prodiv.getElementsByTagName("DIV")[0].style.display = "none";
prodiv.getElementsByTagName("SPAN")[1].innerHTML = err;
httpUP.abort();
flag = true;
uplist[nowID].state = 3;
return;
}
if (state == "OK") {
prodiv.getElementsByTagName("DIV")[0].style.display = "none";
var tmpf = uplist[nowID].file;
prodiv.getElementsByTagName("SPAN")[1].innerHTML = "文件名:"
+ tmpf.name;
window.clearInterval(timer);
flag = true;
uplist[nowID].state = 2;
uplist[nowID].path = path;
return;
}
prodiv.getElementsByTagName("DIV")[1].style.width = per * 5 + "px";
prodiv.getElementsByTagName("SPAN")[0].innerHTML = per + "%";
}
}
}
/**
* 撤消上傳的辦法
*/
function abortUpload(obj) {
var idStr = obj.parentNode.id;
var id = idStr.slice(3);
if (uplist[id].state == 1) {
httpUP.abort();
flag = true;
cancelFlag = 1;
} else {
uplist[id].state = 3;
}
document.getElementById(idStr).remove();
}
/**
* 獲得上傳文件的途徑
* @returns 格局化後字符串
*/
function getFileListStr() {
var str = "";
if (oldFileList.length > 0) {
for ( var i = 0; i < oldFileList.length; i++) {
if (oldFileList[i] != null & oldFileList[i] != ""
& oldFileList[i] != undefined) {
str = str + oldFileList[i] + ",";
}
}
}
for ( var i = 0; i < uplist.length; i++) {
var f = uplist[i];
if (f.state == 2) {
str = str + f.path + ",";
}
}
return str;
}
/**
* 移除修正時已有的舊附件
*
*/
function removeOld(btn) {
var num = btn.getAttribute("name");
oldFileList[num - 1] = null;
btn.parentNode.remove();
}
function uploadProgress(e) {
if (e.lengthComputable) {
var iBytesUploaded = e.loaded;
var iBytesTotal = e.total;
document.getElementById("test").innerHTML=iBytesUploaded+"/"+iBytesTotal;
}
}
應用ajax發奉上傳文件,獲得上傳進度,成果等信息。
應用的html5的file API,所以必需ie9以上的才可以兼容,火狐還有個成績,ajax要求不立刻前往,直到一切ajax要求都發送完了,才都前往統一個成果,這就招致上傳進度不顯示。不外上傳進度信息也能夠應用html5的file api獲得,個中加了一點代碼,頁面上面test的div裡的數值就是在前端獲得到的進度。
上傳的都完成完了,接著是處置上傳後的暫時文件,由於應用的uuid定名文件,所以文件會生成許多,沒用的須要准時處置。應用ServletContextListener:
在 Servlet API 中有一個 ServletContextListener 接口,它可以或許監聽 ServletContext 對象的性命周期,現實上就是監聽 Web 運用的性命周期。
當Servlet 容器啟動或終止Web 運用時,會觸發ServletContextEvent 事宜,該事宜由ServletContextListener 來處置。在 ServletContextListener 接口中界說了處置ServletContextEvent 事宜的兩個辦法。
應用其特征,完成准時刪除暫時文件的功效,代碼以下:
package util.upload;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 時光監聽器
*
*
*/
public class TempFileListener implements ServletContextListener {
private Timer timer;
private SystemTaskTest systemTask;
private static String every_time_run;
static {
Properties prop = new Properties();
InputStream inStrem = TempFileManager.class.getClassLoader()
.getResourceAsStream("tempfile.properties");
try {
prop.load(inStrem);
System.out.println(inStrem);
every_time_run = prop.getProperty("every_time_run");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inStrem.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 監聽器初始辦法
public void contextInitialized(ServletContextEvent sce) {
timer = new Timer();
systemTask = new SystemTaskTest(sce.getServletContext()
.getRealPath("/"), sce.getServletContext());
try {
System.out.println("准時器已啟動");
// 監聽器獲得網站的根目次
String path = sce.getServletContext().getRealPath("/");
Long time = Long.parseLong(every_time_run) * 1000;// 輪回履行的時光
System.out.println("time" + time);
// 第一個參數是要運轉的代碼,第二個參數是從甚麼時刻開端運轉,第三個參數是每隔多久在運轉一次。反復履行
timer.schedule(systemTask, 10000, time);
System.out.println("曾經添加義務調劑表");
} catch (Exception e) {
e.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent sce) {
try {
timer.cancel();
} catch (Exception e) {
}
}
}
/**
* 時光義務器
*
*/
class SystemTaskTest extends TimerTask {
private ServletContext context;
private String path;
public SystemTaskTest(String path, ServletContext context) {
this.path = path;
this.context = context;
}
/**
* 把要准時履行的義務就在run中
*/
public void run() {
TempFileManager etf;
try {
System.out.println("開端履行義務!");
// 須要履行的代碼
System.out.println(new Date().toLocaleString());
etf = new TempFileManager(path);
etf.run();
System.out.println("指定義務履行完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面只是監聽器,擔任准時挪用刪除暫時文件的辦法,詳細完成是上面的類
package util.upload;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
/**
* 刪除辦事器上的文件
*
*/
public class TempFileManager implements Runnable {
private String path;//途徑
private static String RETENTION_TIME = "1440";// 文件保留的時光 一天單元分
static {
Properties prop = new Properties();
InputStream inStrem = TempFileManager.class.getClassLoader()
.getResourceAsStream("execl.properties");
try {
prop.load(inStrem);
RETENTION_TIME = prop.getProperty("file_retention_time");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inStrem.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 結構函數。初始化參數
* @param path
*/
public TempFileManager(String path) {
this.path = path;
}
/**
* 把線程要履行的代碼放在run()中
*/
public void run() {
System.out.println("文件治理開端=========");
path = path + "upload";
System.out.println("文件治理途徑===" + path);
File file = new File(path);
deletefiles(file);
}
/**
* 批量刪除文件
*
* @param folder
*/
public void deletefiles(File folder) {
if(folder.isDirectory()){
File[] files = folder.listFiles();
if(files.length<=0){
if(!folder.getAbsolutePath().equalsIgnoreCase(path)){
if(canDeleteFile(folder)){
if (folder.delete()) {
System.out.println("文件夾" + folder.getName() + "刪除勝利!");
} else {
System.out.println("文件夾" + folder.getName()
+ "刪除掉敗!此文件夾內的文件能夠正在被應用");
}
}
}
}
for (int i = 0; i < files.length; i++) {
if(files[i].isDirectory())
{
deletefiles(files[i]);
}else{
deleteFile(files[i]);
}
}
}
}
/**
* 刪除文件
*
* @param file
*/
private void deleteFile(File file) {
try {
if (file.isFile()) {
// 刪除相符前提的文件
if (canDeleteFile(file)) {
if (file.delete()) {
System.out.println("文件" + file.getName() + "刪除勝利!");
} else {
System.out.println("文件" + file.getName()
+ "刪除掉敗!此文件能夠正在被應用");
}
} else {
}
} else {
System.out.println("沒有可以刪除的文件了");
}
} catch (Exception e) {
System.out.println("刪除文件掉敗========");
e.printStackTrace();
}
}
/**
* 斷定文件能否可以或許被刪除
*/
private boolean canDeleteFile(File file) {
Date fileDate = getfileDate(file);
Date date = new Date();
long time = (date.getTime() - fileDate.getTime()) / 1000 / 60
- Integer.parseInt(RETENTION_TIME);// 以後時光與文件距離的分鐘
// System.out.println("time=="+time);
if (time > 0) {
return true;
} else {
return false;
}
}
/**
* 獲得文件最初的修正時光
*
* @param file
* @return
*/
private Date getfileDate(File file) {
long modifiedTime = file.lastModified();
Date d = new Date(modifiedTime);
return d;
}
}
斷定文件能否超時,超時就主動刪除,而且能主動刪除文件夾。
以上就是本文的全體內容,願望對年夜家進修java法式設計有所贊助。