天天看點

jsp利用smartLoad實作上傳下載下傳

1.在填寫表單時需要進行日期、數字等校驗,這可以用jQuery easyUI來實作,非常友善。

使用jquery easyui時需導入類似jquery-easyui-1.3.1的包,然後在jsp頁面引入相應的檔案,一般來說是4個。

<!-- 先引入jquery核心檔案,剩下的引入順序就無所謂 -->
<script type="text/javascript" charset="utf-8" src="js/jquery-easyui-1.3.1/jquery-1.8.0.min.js"></script>
<!-- 引入easy_ui的css樣式檔案 -->
<link rel="stylesheet" type="text/css" href="js/jquery-easyui-1.3.1/themes/default/easyui.css" target="_blank" rel="external nofollow" >
<!-- 引入easy_ui的js -->
<script type="text/javascript" charset="utf-8" src="js/jquery-easyui-1.3.1/jquery.easyui.min.js"></script>
<!-- 引入國際化檔案 -->
<script type="text/javascript" charset="utf-8" src="js/jquery-easyui-1.3.1/locale/easyui-lang-zh_CN.js"></script>
           

2.上傳時需注意兩點,method="post"和enctype="multipart/form-data".

3.BaseDao是一個最基本的接口,裡邊定義了增删改查資料庫的方法,使用時直接繼承就好了。如:

public interface BaseDao<Entity> {//Entity也可以換成其他值,一般換為T,然後所有的Entity都換成T才可以,泛型的一種寫法
	void save(Entity entity) throws Exception;//儲存
	void view(Entity entity) throws Exception;//展示
	void update(Entity entity) throws Exception;//更新
	void delete(int id) throws Exception;//根據id删除指定資料
	Entity findById(int id) throws Exception;//根據id查詢指定記錄
	List<Entity> findAll() throws Exception;//查詢所有記錄
}
           

4.

ParameterizedType pz = (ParameterizedType) this.getClass().getGenericSuperclass();
//利用反射傳回目前類的父類的類型,并強制轉換
           

5.BaseDaoImpl中有

String methodName = "get" + fs[i].getName().substring(0,1).toUpperCase()+ fs[i].getName().substring(1);
String methodName = "get" + Character.toUpperCase(fs[i].getName().charAt(0))+ fs[i].getName().substring(1);
           

這兩句是等效的。

6.若想擷取request,可用類似下邊的方法

SamrtUpload su = new SmartLoad();
Request req = su.getRequest();
           

7.String型轉化為int型

int id = Integer.parseInt(request.setParameter("id"));
//因為request.setParameter()擷取的都為string類型
           

8.若想讓表的自增索引從0開始,則可以用

truncate 表名;這相當于删除表重建

9.傳遞方法時不用打單引号或雙引号,否則會找不到該方法.如:

<form action="UserServlet?method=save">;//正确
<form action="UserServlet?method='save'">;//可能會出錯
           

10.根據id删除時

String sql = "delete from " + clazz.getSimpleName() + " where id = " + id;//注意空格
           

" where id = "的id後不能加問号,因為後邊已經有了變量值,不用占位

查找時

String sql = "select * from " + clazz.getSimpleName() + " where id= ? ";
           

而這" where id= ? "需加問号,因為要占位

11.el表達式中,如果要做判斷某值是否為空,可以用

<c:if test="${user.path ne null }">//ne表示不相等

<c:if test="${user.path eq null }">//eq表示相等
           

12.在使用Myeclipse時也遇到問題,就是以前隻要一開啟伺服器,界面就自動跳轉到console控制台,今天不知啥原因不跳了,網上查了才知道,在Window-preferences-Run/Debug-Console,下邊有兩個show選項,"Show when program writest to standard out"和"Show when program writes to standard error,都勾上時就會自動跳轉,不選擇就不跳。

13.關于basePath和realPath

SmartUpload su = new SmartUpload();//建立上傳下載下傳對象,對,smartUpload也可以下載下傳
File file = su.getFiles().getFile(0);擷取上傳的檔案,因為隻上傳了一個檔案,是以為0
ServletContext sc = new ServletContext();//擷取ServletContext對象,該對象用于共享資料
String basePath = sc.getRealPath("/upload");//定義檔案上傳位置
//輸出的basePath為E:\Program Files\apache-tomcat-6.0.14\webapps\upload\upload
//其中第一個upload為項目名稱,第二個upload為上傳的位置。雖然想把檔案上傳至項目的檔案夾中
//但上傳至伺服器是無争議的,因為tomcat就是伺服器,是以會上傳到那個位置
String realPath = basePath + "/" + UUID.randomUUID().toString() + file.getFileName();//假設檔案名為001.jpg
//列印出的realPath為E:\Program Files\apache-tomcat-6.0.14\webapps\upload\upload/b9e47b6b-c656-41f0-a1c2-828087a011ad001.jpg
//加UUID是為了防止檔案重名
           

14.下面貼兩段代碼,以後可以直接拿來用

①BaseDaoImpl中的代碼,利用反射擷取方法,注意裡邊的注釋

/**
 * 利用反射擷取
 * 
 */

package com.bjsxt.base;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.bjsxt.util.DBUtil;

public class BaseDaoImpl<Entity> implements BaseDao<Entity> {
	
	protected Class clazz;
	
	public BaseDaoImpl(){
		ParameterizedType pz = (ParameterizedType) this.getClass().getGenericSuperclass();
		//利用反射傳回目前類的父類的類型,并強制轉換
		clazz = (Class) pz.getActualTypeArguments()[0];
		//傳回此類型實際類型參數的Type對象數組的第一個
		//這兩步的作用就是擷取父類泛型參數的實際類型
		//System.out.println(clazz + "這是測試代碼,列印出來的");
		
		//列印得出clazz為class com.bjsxt.po.User
		
	}
	
	
	@Override
	public void save(Entity entity) throws Exception {
		Connection conn = DBUtil.getConn();//連接配接資料庫
		String sql = "insert into " + clazz.getSimpleName() + " values(null";
		Field[] fs = clazz.getDeclaredFields(); 
		for (int i = 1; i < fs.length; i++) {//這裡要注意i要從1開始,因為資料庫下标是從1開始,否則會出問題
			sql += ",?";
		}
		sql = sql + ")";
		PreparedStatement ps = DBUtil.getPs(conn, sql);
		//user.setUsername(rs.getString("username"));
		for (int i = 1; i < fs.length; i++) {//這裡也要注意i要從1開始
			String methodName = "get" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
			//也可寫為String methodName = "get" + fs[i].getName().substring(0,1).toUpperCase()+ fs[i].getName().substring(1);
			//假如有個實體user類,含有uname屬性,則擷取uname的方法預設會為getUname(),會将uname的首字母大寫,其餘不變
			//Character.toUpperCase就是将字元大寫,然後将除首字母以外的截取出來,拼到一起,構成類似于getUname()的方法
			//user.setUsername(uForm.getUsername);  
			//該處用get是因為要把對象儲存進資料庫裡,用get擷取屬性
			Method m = clazz.getDeclaredMethod(methodName);
			ps.setObject(i,m.invoke(entity));
			//setObject用來給"?"指派。invoke則是在不知道具體類的情況下利用字元串去調用方法
			//正常情況下是user.getUsername,m.invoke(entity)中m是一個方法,類似于getUsername(),entity相當于user.
			//invoke是從實體裡邊找方法,那句話的意思就是從實體裡邊調用方法
		}
		ps.executeUpdate();
		DBUtil.close(ps);
		DBUtil.close(conn);
	}

	@Override
	public void view(Entity entity) throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void update(Entity entity) throws Exception {
		Connection conn = DBUtil.getConn();
		String sql = "update " + clazz.getSimpleName() + " set ";//注意這兒的set兩旁的空格,否則會出錯,蛋疼
		Field[] fs = clazz.getDeclaredFields();
		for (int i = 1; i < fs.length; i++) {//下标從1開始
			sql += fs[i].getName() + " = ?,";
		}
		sql = sql.substring(0,sql.length()-1) + " where id = ?"; //減去最後的逗号
		PreparedStatement ps = DBUtil.getPs(conn, sql);
		for (int i = 1; i < fs.length; i++) {//注意下标從1開始
			String methodName = "get" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
			System.out.println(methodName+"這是methodName");
			Method m = clazz.getDeclaredMethod(methodName);
			ps.setObject(i, m.invoke(entity));
		}
		Method getId = clazz.getDeclaredMethod("getId");//更新需要知道id
		ps.setInt(fs.length, (Integer) getId.invoke(entity));//因為id在sql語句最後一個問号處,是以要用fs.length
		ps.executeUpdate();
		DBUtil.close(ps);
		DBUtil.close(conn);
		
	}

	@Override
	public void delete(int id) throws Exception {
		Connection conn = DBUtil.getConn();
		//String sql = "delete from " + clazz.getSimpleName() + " where id = ?" + id;
		//上句為錯誤寫法,不能加問号,因為後邊已經有了變量值,不用占位
		String sql = "delete from " + clazz.getSimpleName() + " where id = " + id;
		PreparedStatement ps = DBUtil.getPs(conn, sql);
		ps.executeUpdate();
		DBUtil.close(ps);
		DBUtil.close(conn);
	}

	@Override
	public Entity findById(int id) throws Exception {
		Connection conn = DBUtil.getConn();
		String sql = "select * from " + clazz.getSimpleName() + " where id= ? ";
		PreparedStatement ps = DBUtil.getPs(conn, sql);
		ps.setInt(1,id);
		ResultSet rs = ps.executeQuery();
		Entity entity = (Entity) clazz.newInstance();//利用無參構造函數建立執行個體
		Field[] fs = clazz.getDeclaredFields();
		if(rs.next()){
			for (int i = 0; i < fs.length; i++) {
				String methodName = "set" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
				Method m = clazz.getDeclaredMethod(methodName, fs[i].getType());
				m.invoke(entity, rs.getObject(fs[i].getName()));
			}
		}
		DBUtil.close(rs);
		DBUtil.close(ps);
		DBUtil.close(conn);
		
		return entity;
	}

	@Override
	public List<Entity> findAll() throws Exception {
		Connection conn = DBUtil.getConn();
		String sql = "select * from " + clazz.getSimpleName();
		PreparedStatement ps = DBUtil.getPs(conn, sql);
		ResultSet rs = ps.executeQuery();
		List<Entity> enList = new ArrayList<Entity>();
		while(rs.next()){
			Entity en = (Entity) clazz.newInstance();
			//user.setUsername(rs.getString("username"));
			Field[] fs = clazz.getDeclaredFields();
			for (int i = 0; i < fs.length; i++) {
				String methodName = "set" + Character.toUpperCase(fs[i].getName().charAt(0)) + fs[i].getName().substring(1);
				Method m = clazz.getDeclaredMethod(methodName, fs[i].getType());
				m.invoke(en, rs.getObject(fs[i].getName()));
			}
			enList.add(en);
		}
		DBUtil.close(rs);
		DBUtil.close(ps);
		DBUtil.close(conn);
		return enList;
	}
	
}
           

②利用SmartUpload控制上傳下載下傳的servlet

package com.bjsxt.action;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

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

import com.bjsxt.dao.UserDao;
import com.bjsxt.dao.impl.UserDaoImpl;
import com.bjsxt.po.User;
import com.jspsmart.upload.File;
import com.jspsmart.upload.Request;
import com.jspsmart.upload.SmartUpload;

public class UserServlet extends HttpServlet {
	
	private UserDao udao = new UserDaoImpl();//這條不能忘,很重要
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String method = request.getParameter("method");
		if("save".equals(method)){
			this.save(request,response);
		}else if("view".equals(method)){
			this.view(request,response);
		}else if("preUpdate".equals(method)){
			this.preUpdate(request,response);
		}else if("delete".equals(method)){
			this.delete(request,response);
		}else if("update".equals(method)){
			this.update(request,response);
		}else if("download".equals(method)){
			this.download(request,response);
		}
	}
	
	
	/**
	 * 添加使用者資訊
	 * @param request
	 * @param response
	 */
	private void save(HttpServletRequest request, HttpServletResponse response) {
		try {
			//1.建立上傳下載下傳對象
			SmartUpload su = new SmartUpload();
			//2.初始化上傳下載下傳
			su.initialize(this.getServletConfig(),request,response);
			//3.設定上傳的限制内容
			su.setMaxFileSize(400000);//單個檔案的最大上傳大小
			su.setTotalMaxFileSize(100000000);//總上傳檔案大小
			su.setAllowedFilesList("jpeg,png,jpg,gif");//設定限制的檔案類型
			su.setDeniedFilesList("exe,doc,ppt");//設定不允許上傳的檔案類型
			//4.開始上傳
			su.upload();
			
			File file = su.getFiles().getFile(0);//擷取上傳的檔案,因為隻上傳了一個檔案,是以為0
			String realPath = null;//檔案上傳的真實路徑
			
			if(file.getSize()>0){
				ServletContext sc = this.getServletContext();//得到servletContext執行個體
				String basePath = sc.getRealPath("/upload");
				//擷取上傳的絕對路徑,因為上傳至web伺服器的虛拟路徑
				/******************************************************************/
				System.out.println("bathPath為" + basePath);
				//輸出為E:\Program Files\apache-tomcat-6.0.14\webapps_upload_upload
				
				
				
				realPath = basePath + "/" + UUID.randomUUID().toString() + file.getFileName(); 
				System.out.println("realPath為" + realPath);
				//列印為E:\Program Files\apache-tomcat-6.0.14\webapps_upload_upload/c402cc92-7644-4259-8232-22dd8c63605e1hhWO.gif
				/******************************************************************/
				file.saveAs(realPath);//将檔案換名另存
			}
			Request req = su.getRequest();
			String uname = req.getParameter("username");
			String pwd = req.getParameter("pwd");
			String salary = req.getParameter("salary");
			String birthday = req.getParameter("birthday");
			//String path = req.getParameter("path");
			
			User user = new User();
			user.setUsername(uname);
			user.setPwd(pwd);
			user.setSalary(salary);
			user.setBirthday(birthday);
			user.setPath(realPath);//這一步也必須有,否則圖檔存不進資料庫
			
			this.udao.save(user);//将所加資訊儲存到對象中
			response.sendRedirect("UserServlet?method=view");//将結果發送到展示頁面一律用sendRedirect
			//注意這裡不是發送到user_view.jsp,而是發送到本UserServlet的view方法,而且view不能打單引号,血的教訓
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 展示使用者資訊
	 * @param request
	 * @param response
	 */
	private void view(HttpServletRequest request, HttpServletResponse response) {
		try{
			//List<User> ulist = new ArrayList<User>();
			//不能這樣寫,否則ulist會永遠是空值
			List<User> ulist = this.udao.findAll();//正确的寫法是這樣
			request.setAttribute("ulist",ulist);//将對象添加到作用域中
			request.getRequestDispatcher("user_view.jsp").forward(request, response);
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 預修改
	 * @param request
	 * @param response
	 */
	private void preUpdate(HttpServletRequest request,HttpServletResponse response) {
		try {
			User user = this.udao.findById(Integer.parseInt(request.getParameter("id")));
			request.setAttribute("user",user);
			request.getRequestDispatcher("user_update.jsp").forward(request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	private void update(HttpServletRequest request, HttpServletResponse response) {
		try {
			//1:第一次save沒有上傳照片,這次修改也沒有上傳照片
			//2:第一次save沒有上傳照片,這次上傳了照片(smartupload)
			//3:第一次save上傳照片了 ,這次沒有上傳照片
			//4:第一次save上傳照片了,這次也上傳了(smartupload[新上傳的會把舊的覆寫掉])
			
			//1.建立上傳下載下傳對象
			SmartUpload su = new SmartUpload();
			//2.初始化上傳下載下傳
			su.initialize(this.getServletConfig(),request, response);
			//3設定上傳的限制内容
			su.setMaxFileSize(100000);		//單個檔案的最大上傳限制
			su.setTotalMaxFileSize(500000);	//總檔案上傳最大限制
			su.setAllowedFilesList("doc,txt,jpg,png,gif");	//允許上傳檔案的類型
			su.setDeniedFilesList("exe,bat,html,htm,,");//不允許上傳檔案的類型
			//4開始上傳
			su.upload();
			
			Request req = su.getRequest();
			String id = req.getParameter("id");
			String uname = req.getParameter("username");
			String salary = req.getParameter("salary");
			String birthday = req.getParameter("birthday");
			
			User user = this.udao.findById(Integer.parseInt(id));
			String realPath = user.getPath();//之前資料庫裡的圖檔路徑
			
			System.out.println("之前資料庫的圖檔路徑realPath為"+realPath);
			
			File file = su.getFiles().getFile(0);
			
			if(file.getSize()>0){
				if(realPath!=null){
					java.io.File f = new java.io.File(realPath);
					if(f.exists()){
						f.delete();
					}
					
				}
				ServletContext sc = this.getServletContext();
				//String basePath = sc.getRealPath(realPath);//錯誤寫法,找這個快蛋碎而亡了
				String basePath = sc.getRealPath("/upload");//這才是正确的寫法
				System.out.println("/************************************************/");
				System.out.println(realPath);
				realPath = basePath + "/" + UUID.randomUUID().toString() + file.getFileName();
				System.out.println("/************************************************/");
				System.out.println(realPath);
				file.saveAs(realPath);
			}
			
			user.setBirthday(birthday);
			user.setUsername(uname);
			user.setSalary(salary);
			user.setPath(realPath);//注意該處為realPath
			
			this.udao.update(user);//注意此處為update,不是save
			response.sendRedirect("UserServlet?method=view");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

	/**
	 * 删除方法
	 * @param request
	 * @param response
	 */
	private void delete(HttpServletRequest request, HttpServletResponse response) {
		try {
			String id = request.getParameter("id");
			//System.out.println(id);
			this.udao.delete(Integer.parseInt(id));
			response.sendRedirect("UserServlet?method=view");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 下載下傳照片
	 * @param request
	 * @param response
	 */
	private void download(HttpServletRequest request,HttpServletResponse response) {
		try {
			String path = request.getParameter("path");
			String imageName = new String("照片".getBytes("utf-8"),"iso-8859-1");
			//如果需要檔案名中附加中文,需要轉碼
			imageName += path.substring(path.lastIndexOf("."));
			//拼接帶中文的檔案名,以後隻要下載下傳,就隻有一種預設的檔案名"照片.jpg"或"照片.bmp"等
			
			//設定response對象的響應頭内容
			response.setContentType("application/x-download");
			response.addHeader("Content-Disposition", "anttachment;filename="+imageName);
			
			//寫出圖檔
			FileInputStream fis = new FileInputStream(path);
			OutputStream os = response.getOutputStream();
			
			int temp = 0;
			byte[] bs = new byte[256];//設定緩存大小
			while((temp=fis.read(bs))!=-1){
				os.write(bs,0,temp); //寫出檔案
			}
			fis.close();
			os.flush();
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}
           

說在最後邊的,這代碼還是得多練,雖然現在很蛋疼吐血。