基礎知識在前面一篇,檔案上傳代碼。耐心看到後面的重構,簡潔多了
重構代碼下載下傳:http://download.csdn.net/detail/xiaozhegaa/9782629
(一) 開發思路:代碼看起來有點亂,但是是有思路的
1:工廠–>對象設計模式。建立工廠—–>設定一下工廠的屬性,其中涉及了臨時檔案,那麼在源碼第一二行先取得上傳的真實路徑和臨時路徑
2:得到對象,先設定上傳檔案的字元編碼問題,然後判斷是否是MIME協定送出
> 3.1:若不是MIME協定送出,抛異常,提示說要用MIME送出,若不然就收集不到資料哦
>> 3.2 : 若是MIME協定送出,則要把上傳的内容轉化成FileItemList。也就是用parseRequest()
4:取到list集合之後,循環周遊,判斷是否是普通字段
>> 5:如果是普通字段的話,那麼采用一般的bean裝在就可以 //user.getUsername(“xxx”)
> > 6:否則就檔案字段,那麼對檔案進行處理
7:這是擴充的功能:各種if
>>7.1 :if(fileItem.endWith(“jpg”)) //上傳是jpg,給不給通過
>>7.2 :if(fileItem.getSize()==0) //空檔案,給不給通過,還是抛異常
> >7.3 :if(fileItem.gizeSize() > 1024 * 200) //檔案大于200k,給不給通過
> >7.4 :………等等
8:然後就讀寫資料,is.readLine(),os.write()。java基礎固定寫法
9:删除臨時檔案
10:顯示上傳成功頁面
public class UploadServlet2 extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//取得上傳的真實路徑和臨時路徑
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
//使用第一個類u
//建立上傳檔案的工廠
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
//設定記憶體中的緩沖區大小。10k
fileItemFactory.setSizeThreshold(*);
//設定上傳檔案臨時存放的目錄
fileItemFactory.setRepository(new File(tempPath));
//使用第二個類
//建立上傳檔案的對象
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
//設定上傳檔案名字的字元編碼
servletFileUpload.setHeaderEncoding("UTF-8");
//判斷用戶端是否是采用那個了mime協定去上傳檔案
boolean flag = servletFileUpload.isMultipartContent(request);
if(!flag){
//也就是不是采用mime的協定上傳檔案,那麼抛異常。這裡也可以采用一般的方式去處理哦哦
throw new ServletException();
}else{
/*也就是說是采用了MIME的協定上傳檔案
* 解析request中的所有上傳内容,并且把每個内容解析成fileItem對象
* fileItem代表的是普通字段跟檔案字段兩類
*/
try {
//使用第三個類
List<FileItem> fileItemList = servletFileUpload.parseRequest(request);
for(FileItem fileIem :fileItemList){
if(fileIem.isFormField()){
//如果說是普通的字段
String fileName = fileIem.getFieldName();
String fileValue = fileIem.getString("UTF-8");
System.out.println(fileName+"-----"+fileValue);
}else{
//這裡是檔案上傳字段
String realFileName = fileIem.getName();
/*
* 對于ie浏覽器的話上傳路徑是C:\Users\admin\Desktop\1.jpg,
* 而對于一些進階浏覽器火狐之類的路徑是1.jpg。
是以要對路徑做一個處理。隻需要1.jsp就可以
*/
int index = realFileName.lastIndexOf("\\");
if(index>=){
//确實是ie浏覽器
realFileName = realFileName.substring(index+);
}
//通過真實的檔案名換算出一個唯一的一個檔案名
String makeUuidFileName = makeUuidFileName(realFileName);
//通過位運算換算出upload檔案夾下面的子檔案夾
String makeUuidFilePath = makeUuidFilePath(uploadPath,makeUuidFileName);
/*
*在讀取檔案之前可以先進行一系列判斷,如果判斷不通過,不給送出
*例如
*/
//如果無上傳檔案
if(fileItem.getSize()==){
throw new NoUpfileException();
}
//隻能上傳JPG檔案
if(!realFileName.endsWith("JPG")){
throw new UpfileTypeException();
}
//隻有上傳<=200K的檔案
if(fileItem.getSize() > * ){
throw new UpfileSizeException();
}
//等等各種限制條件,自己寫
//獲得到檔案輸入流
InputStream is = fileIem.getInputStream();
//取得檔案輸出流
OutputStream os = new FileOutputStream(makeUuidFilePath+"/"+makeUuidFileName);
byte[] buf = new byte[];
int len = ;
while((len = is.read(buf)) > ){
os.write(buf, , len);;
}
is.close();
os.close();
//将上傳檔案的臨時檔案删除
fileIem.delete();
request.setAttribute("message", "上傳成功");
request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
request.setAttribute("message","上傳檔案失敗");
request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request,response);
}
}
}
/**
*這個是防止說一個目錄檔案過多,采用&方式去推出二級目錄之類的函數
*/
private String makeUuidFilePath(String uploadPath, String makeUuidFileName) {
String uuidFilePath = null;
int code = makeUuidFileName.hashCode(); //獲得到檔案的hascode碼 8
int dir1 = code & ; //3
int dir2 = code & ; //8
File file = new File(uploadPath+"/"+dir1+"/"+dir2);
if(!file.exists()){
//如果說檔案路徑不存在的話,那麼就一次建立多個目錄
file.mkdirs();
}
uuidFilePath = file.getPath();
return uuidFilePath;
}
/**
*寫一個算法,給每一張圖檔起一個唯一的名字,這樣在上傳同一張圖檔的時候就可以有多個
* @param fileName 圖檔的名字,最後加上檔案的名字識别
* @return
*/
public String makeUuidFileName(String fileName){
return UUID.randomUUID().toString()+"_"+fileName;
}
</font>
(二) 第一種重構的方式比較簡單:也就是把原代碼中能夠抽取出來的方法,全部抽取出來放在一個UploadUtil類中,然後再原來的方法中調用該靜态方法就可以
注意:這裡的源碼沒有列舉出來,隻是列舉方法名而已。具體的實作源碼我已經導成了一個jar包。如果有興趣的可以下載下傳該jar包研究一下啊。或者學習者自己重構
//取得上傳的真實路徑和臨時路徑
public static final String tempPath = "/WEB-INF/temp";
public static final String uploadPath ="/WEB-INF/upload";
/*
* 對于ie浏覽器的話上傳路徑是C:\Users\admin\Desktop\1.jpg,
* 而對于一些進階浏覽器火狐之類的路徑是1.jpg。
是以要對路徑做一個處理。隻需要1.jsp就可以
*/
public static String getRealFileName(String realFileName){
//代碼忽略了 return 1.jpg
return realFileName;
}
/**取得upload目錄下面的子目錄
* @param uploadPath :upload
* @param makeUuidFileName : a.jpg
* @return upload/8/8
*/
public static String makeUuidFilePath(String uploadPath, String makeUuidFileName) {
//代碼忽略了 傳回 upload/8/8
return uuidFilePath;
}
/**
* 取得檔案的uuid名字
*寫一個算法,給每一張圖檔起一個唯一的名字,這樣在上傳同一張圖檔的時候就可以有多個
* @param fileName 圖檔的名字,最後加上檔案的名字識别
* @return
*/
public static String makeUuidFileName(String fileName){
return UUID.randomUUID().toString()+"_"+fileName;
}
/*
*檔案儲存,也就是Io流那個
*/
public static void doSave(InputStream is,String makeUuidFilePath ,String makeUuidFileName){
//代碼忽略了 傳回 true/false
return true/false
}
(三)第二種重構就更加的簡潔了
隻需要調用
UploadUtil.doUpload();
UploadUtil.doSave();
兩個方法就可以實作儲存。
這種簡介的代碼才是我們所追求的。
測試案例:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws Exception {
try {
User user = UploadUtil.doUpload(request);
String uploadPath = this.getServletContext().getRealPath(UploadUtil.uploadPath);
UploadUtil.doSave(user,uploadPath);
request.setAttribute("message", "上傳成功");
request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);
} catch (FileUploadException e) {
e.printStackTrace();
request.setAttribute("message", "上傳失敗");
request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);
}
}
//第二種封裝方式,把上傳檔案分裝成javaBean
public static User doUpload(HttpServletRequest request) throws Exception{
//代碼忽略了
return user;
}
//javaBean的儲存檔案
public static void doSave(User user,String uploadPath) throws IOException{
//代碼忽略了
}