`

servlet上传文件(后)

阅读更多

负责上传文件的servlet
package upload;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.Hashtable;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class UploadFileServlet extends HttpServlet {
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		final int NONE = 0; //状态码,标识没有特殊操作
		final int DATAHEADER = 1;  //标识下一行要读到的抱头信息
		final int FILEDATA = 2;  //表示下面要读到表单域的文本值
		final int FIELDDATA = 3;  //表示下面要读的是二进制文件和二进制数据
		int totalbytes = request.getContentLength(); //请求消息实体的总长度(请求消息中除了消息头之外的数据长度)
		byte[] b = new byte[totalbytes]; //保存请求消息实体的 数组
		String contentType = request.getContentType(); //请求消息类型

		String fieldname = "";     //表单域的名称

		String fieldvalue = "";//表单域的值

		String filename = ""; //上传的文件的名字
		String boundary = "";  //分界符字符串
		String lastBoundary = ""; //结束分界符字符串
		int fileSize = 0; //文件长度

		Hashtable<String,String> formfields = new Hashtable<String,String>();  //保存表单域的名称/值的哈希表
		int pos = contentType.indexOf("boundary="); //在消息头中找到分界符的定义
		String fileID; // 上传文件的id
		if (pos != -1) {
			pos += "boundary=".length();
			boundary = "--" + contentType.substring(pos); //解析出分界符
			lastBoundary = boundary + "--";  //得到结束分界符
		}

		int state = NONE; //起始状态是none
		DataInputStream in = new DataInputStream(request.getInputStream()); //请求消息的数据输入流
		in.readFully(b); //根据长度,将消息实体的内容读入字节数组b中
		in.close();
		String reqcontent = new String(b);

		BufferedReader reqbuf = new BufferedReader(new StringReader(reqcontent));//从字符串中得到输出缓冲流

		boolean flag = true; //循环标识
		int i = 0;
		while (flag == true) {
			String s = reqbuf.readLine();
			if (s == null || s == lastBoundary)
				break;
			switch (state) {
			case NONE:
				if (s.startsWith(boundary)) {
					state = DATAHEADER;
					i += 1;
				}
				break;
			case DATAHEADER:
				pos = s.indexOf("filename="); //先判断出这是一个文本表单域的头信息,还是一个上传文件的头信息
				if (pos == -1) {
					pos = s.indexOf("name=");  //如果是文本表单域的头信息,解析出表单域的名称
					pos += "name=".length() + 1;
					s = s.substring(pos);
					int l = s.length();
					s = s.substring(0, l - 1);
					fieldname = s;  //表单域的名称放入filename
					state = FIELDDATA; //设置状态吗,准备读取表单域的值

				} else {//如果是文件数据的头,先存储这一行,用于在字节数组中定位
					String temp = s;
//					先解析出文件名
					pos = s.indexOf("filename=");
					pos += "filename=".length() + 1;
					s = s.substring(pos);
					int l = s.length();
					s = s.substring(0, l - 1);
					pos = s.lastIndexOf("\\");
					s = s.substring(pos + 1);
					filename = s;
					pos = byteIndexOf(b, temp, 0); //定位行

					b = subBytes(b, pos + temp.getBytes().length + 2, b.length); //定位下一行,2标识一个回车和一个换行站2字节
					s = reqbuf.readLine();
					File f = new File(filename); //准备文件输入流,准备写文件

					DataOutputStream fileout = new DataOutputStream(
							new FileOutputStream(f));

					b = this.subBytes(b, s.getBytes().length + 4, b.length);
					pos = this.byteIndexOf(b, boundary, 0);  //定位文件数据的结尾

					b = this.subBytes(b, 0, pos - 1); //取得文件数据

					fileout.write(b, 0, b.length -1); //将文件数据存盘
					fileSize = b.length - 1;  //文件长度
					state = FILEDATA;

				}
				break;
			case FIELDDATA: //读取表单域的值
				s = reqbuf.readLine();
				fieldvalue = s;
				formfields.put(fieldname, fieldvalue);
				state = NONE;
				break;

			case FILEDATA:
				while ((!s.startsWith(boundary))
						&& (!s.startsWith(lastBoundary))) {
					s = reqbuf.readLine();
					if (s.startsWith(boundary)) {
						state = DATAHEADER;
					} else
						break;
					
				}
				break;

			}    // switch

		}    // while

		response.setContentType("text/html;charset=gb2312");//指定内容类型,并且可显示中文
		PrintWriter out = response.getWriter();
		out
				.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
		out.println("<HTML>");
		out.println("  <HEAD><TITLE>文件上传结果</TITLE></HEAD>");
		out.println("  <BODY>");
		out.println("<h1>文件上传结果</h1>");
		out.println("ID 为" + formfields.get("FileID") + "的文件" + filename
				+ "已经上传!" + "文件长度为:" + fileSize + "字节");

		out.println("  </BODY>");
		out.println("</HTML>");
		out.flush();
		out.close();
	}

	private static byte[] subBytes(byte[] b, int from, int end) {
		byte[] result = new byte[end - from];
		System.arraycopy(b, from, result, 0, end - from);

		return result;
	}

	private  static int byteIndexOf(byte[] b, String s, int start) {
		return byteIndexOf(b, s.getBytes(), start);
	}

	private static int byteIndexOf(byte[] b, byte[] s, int start) {

		int i;
		if (s.length == 0) {
			return 0;
		}
		int max = b.length - s.length;
		if (max < 0)
			return -1;
		if (start > max)
			return -1;
		if (start < 0)
			start = 0;
		search: for (i = start; i <= max; i++) {
			if (b[i] == s[0]) {
				int k = 1;
				while (k < s.length) {
					if (b[k + i] != s[k]) {
						continue search;
					}
					k++;
				}
				return i;
			}
		}
		return -1;

	}
	
	
	private static String subBytesString(byte[] b,int from,int end){
		return new String(subBytes(b,from,end));
	}

}


<%@ page language="java" contentType = "text/html;charset=gb2312" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
  
  <body>
    
   <form method ="POST" action ="UploadFileServlet" enctype ="multipart/form-data">
   <p>
				&nbsp; I D:
				<input type="text" name="FileID" size="20">
			</p>
			<p>
				文件:
				<input type="file" name="FileData" size="20">
			</p>
			<p>
				<input type="submit" value="上传" name="uploadfile">
			</p>
    </form>  
    
    
  </body>
</html>


配置文件web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>UploadFileServlet</servlet-name>
    <servlet-class>upload.UploadFileServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>UploadFileServlet</servlet-name>
    <url-pattern>/UploadFileServlet</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

执行结果:






源码见附件
  • 大小: 12.7 KB
  • 大小: 19.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics