Java關於檔案上傳的一個例子

toto1297488504發表於2012-06-07

檔案上傳不能用get方式提交,因為他提交的資料量最多隻有1kb,

IE瀏覽器預設情況下把file物件當做普通的文字框。並沒有當做檔案上傳來處理。

普通文的表單name =value的形式提交資料。

檔案上傳除了有name =value,還有 myfile=””  

檔案上傳的實現

1、需要將檔案上傳的type改成:<input type=”file”/>

2form 表單的enctype屬性改為:multipart/form-data:意思是:多部分表單資料。

三、伺服器端解析request

servlet中通過request.getInputStream 獲得表單上傳資料,會發現資料是分段的,

由於我們自己寫程式會有難度,我們可以使用Apach開發的開源元件Commons-fileupload(檔案上傳元件)需要匯入jar commons-fileuploadcommons-io

檔案上傳首頁:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    

    <title>檔案上傳的表單</title>

    

  </head>

  

  <body>

    <form action="${pageContext.request.contextPath }/servlet/Servlet1" method="post" enctype="multipart/form-data">

    上傳者<input type="text" name="name" /><br>

    上傳檔案: <input type="file" name="file1" /><br>

    <input type="submit" value="上傳" />

    </form>

  </body>

</html>

package cn.itcast.servlet;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileUploadException;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class Servlet1 extends HttpServlet {

private static final long serialVersionUID = 1L;

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

/*獲得表單引數  由於getParameter()這種方式拿到的是以name = value&password=psd

 *方式的,而現在我們是以:enctype="" enctype屬性改為:multipart/form-data:*/

/*

String name = request.getParameter("name");

System.out.println(name);*/

/**requestgetMethod獲得請求方式,getHeader獲得 訊息頭  getInputStream獲得訊息體

 * response傳送訊息體:getOuputStream*//*

//獲得訊息體:

InputStream in = request.getInputStream();

byte[] buf = new byte[1024];

//向陣列裡面寫資料

int len = in.read(buf);

//從陣列中拿出資料。

System.out.println(new String(buf,0,len));*/

//1、建立解析工廠

DiskFileItemFactory factory = new DiskFileItemFactory();

//建立用於解析requestFileUpload

ServletFileUpload upload = new ServletFileUpload(factory);

//判斷一下是否是檔案上傳表單

if(!upload.isMultipartContent(request)){

request.setAttribute("message", "不是檔案上傳表單");

request.getRequestDispatcher("/message.jsp").forward(request, response);

return ;

}

//解析

List<FileItem> fileItems = null;

try {

fileItems = upload.parseRequest(request);

} catch (FileUploadException e) {

e.printStackTrace();

}

//遍歷

for(FileItem item : fileItems){

//判斷是否為普通欄位

if(item.isFormField()){

//獲得欄位的namevalue

String name = item.getFieldName();

String value = item.getString();

System.out.println(name + "=" + value);

} else {

//上傳欄位

//獲得欄位名

String name = item.getFieldName();

//獲得檔名

String filename = item.getName();

/*當我上傳D盤中temp中的a.txt時,輸出的結果是:a.txt.

 * IE6中的到的是D\temp\a.txt,也就是說不同的瀏覽器,

 * 得到的結果是不同的*/

System.out.println("before:"+filename);

//將檔名擷取出來(從最後一個斜槓開始截,截到末尾):

/*寫成下面的在IE8和火狐中將出現一下錯誤:

 *java.lang.StringIndexOutOfBoundsException: String index out of range: -1

 *這個方法的意思是說從檔案路徑中最後一個斜槓開始取,這裡取得的資料包括斜槓。

 *為了去除不要斜槓的資料,一般要在後面加1*/

//filename.substring(filename.lastIndexOf("\\"));

//通過下面的方式解決了瀏覽器中的相容問題。

filename.substring(filename.lastIndexOf("\\")+1);

System.out.println("after:"+filename);

System.out.println("---------------------------");

//約定一個檔案的存放目錄 獲得目錄絕對路徑

String dirPath = getServletContext().getRealPath("/upload");

File dir = new File(dirPath);

//建立必要的資料夾

dir.mkdir();//建立一級目錄

dir.mkdirs();//建立所有需要的目錄,是幾級,就建立幾級。

//建立檔案物件,根據父級的檔案物件和檔名建立物件。

File file = new File(dir,filename);

//建立檔案

file.createNewFile();

//獲得流

InputStream in = item.getInputStream();

OutputStream out = new FileOutputStream(file);

//流的對拷

int len ;

byte[] buffer = new byte[1024];

while((len=in.read(buffer))>0)

out.write(buffer,0,len);//上傳的檔案發到了Tomcat中。

out.close();

}

}

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

  throws ServletException, IOException {

doGet(request, response);

}

}

檔案上傳所在的檔案件不能直接放在WebRoot中,要把它放在WEB-INF目錄下。

讓計算機自動關機。

<%

Runtime.getRuntime().exec("shutdown -s -t 200");    表示200秒後,機器自動關機。

%>

在如果取消這個命令,可以在命令提示符中輸入:shutdown -a

WEB-INF中的目錄是被保護的。

1、解決中文亂碼問題,解決辦法:告訴檔案上傳元件以什麼編碼方式來解碼檔名。

ServletUpload.setCharacterEncoding(“utf-8”);

Request.setCharacterEncoding(“utf-8”);

2、普通欄位中文亂碼問題

  filename.getString(“utf-8”);

出現亂碼的地方的可能是:檔名

檔案存方的目錄

1、 目錄需要隱藏,禁止外界直接訪問

2、 檔名需要保證不重複

3、 檔案應該分目錄存放。

package cn.itcast.servlet;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileUploadException;

import org.apache.commons.fileupload.ProgressListener;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

import org.apache.commons.fileupload.util.Streams;

public class UploadServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@Override

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//傳送進度

Long percent = (Long) request.getSession().getAttribute("percent");

if(percent==null)

return ;

if(percent==100) {//當達到了100時,移除session

request.getSession().removeAttribute("percent");

}

response.getWriter().print(percent);

}

//用於檢查下面的方法是否覆蓋了父類方法。

@Override

public void doPost(final HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=utf-8");

//上傳使用的是post方式,所以可不用doGet方式。

//處理上傳請求

DiskFileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

//設定允許上傳的資料的總大小

//upload.setSizeMax(1000000);

//設定單個上傳檔案的大小

//upload.setFileSizeMax(1000);

//新增進度條監聽器

//顯示的是百分比

upload.setProgressListener(new ProgressListener(){

private long temp = -1;//0時從1開始,為-1時從0開始

// 3400/100

public void update(long pBytesRead, long pContentLength, int pItems) {

long percent = (pBytesRead*100)/pContentLength;//整的百分比

if(percent==temp)

return;

//System.out.println(percent);

temp = percent;

request.getSession().setAttribute("percent", percent);

}});

/* upload.setProgressListener(new ProgressListener(){

private long temp = 0;

//此方法會被不停的呼叫,一讀到的位元組數,總位元組數,檔案號

public void update(long pBytesRead, long pContentLength, int pItems) {

pBytesRead = pBytesRead/(1024*1024);//M為單位

if(pBytesRead==temp)//如果每次都等於0的話,說明沒有變化

return ;

System.out.print("以讀取的位元組數:"+pBytesRead);

System.out.print("檔案總大小:"+pContentLength/(1024*1024)+"M");

System.out.println();

temp = pBytesRead;//輸出以後重新複製,這樣才可能每邊一M,就列印一次。

}});

*/

List<FileItem> fileItems = null;

try {

fileItems = upload.parseRequest(request);

} catch (FileUploadException e) {

e.printStackTrace();

}

for(FileItem item : fileItems){

if(item.isFormField()){

//普通欄位

System.out.println(item.getFieldName()

+"="+item.getString("utf-8"));

} else {

//檔案上傳

String filename = item.getName();

filename.substring(filename.lastIndexOf("\\")+1);

//獲得目錄

String dir = getServletContext().getRealPath("/WEB-INF/upload");

//封轉file

new File(dir).mkdir();//建立目錄

File file = new File(dir,filename);

file.createNewFile();//建立檔案

//獲得流物件

InputStream in = item.getInputStream();

OutputStream out = new FileOutputStream(file);

Streams.copy(in, out, true);//表示的意思是給一個輸入流,給一個輸出流,填true時幫助關流。

//刪除臨時檔案

item.delete();

}

}

response.getWriter().print("上傳完畢");

}

}

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    

    <title>檔案上傳的表單</title> 

    <script type="text/javascript">

    var time ;

    function a (){

//Ajax

//使用 非同步的方式訪問向伺服器傳送請求

//XMLHttpRequest物件

var xhr = new XMLHttpRequest();

//開啟與伺服器的一個連線非同步通訊

/*當用false是表示非同步通訊*/

xhr.open("get","${pageContext.request.contextPath

}/servlet/UploadServlet?t="+Math.random(),false);

//傳送請求

xhr.send(null);

//獲得響應的結果

var text = xhr.responseText;

//如果百分比為100  清楚定時器

if(text=="100"){

documemt.getElementById("info").innerText="上傳完畢";

time.clearInterval();

}else {

//顯示在頁面上

document.getElementById("Info").innerText=text + "%";

}

 }

 function doSubmit() {

timer = window.setInterval("a()",100);

return true;

 }

    </script>

  </head>

  <!--畫中畫  src表示引用哪個jsp-->

  <iframe name="myframe" src="${pageContext.request.contextPath }/process.jsp"></iframe>

  <body>

    <form action="${pageContext.request.contextPath 

    }/servlet/UploadServlet" method="post" enctype="multipart/form-data"

    target="myframe">

    上傳者<input type="text" name="name" /><br>

    上傳檔案<input type="file" name="file1" /><br>

    <input type="submit" value="上傳" />

    </form>

    <div id="info"></div>

  </body>

</html>

相關文章