web端的文件上傳和下載
在Web應用系統開發中,文件上傳和下載功能是非常常用的功能,今天來講一下JavaWeb中的文件上傳和下載功能的實現。
對於文件上傳,瀏覽器在上傳的過程中是將文件以流的形式提交到服務器端的,如果直接使用Servlet獲取上傳文件
的輸入流然後再解析裏面的請求參數是比較麻煩,所以一般選擇採用apache的開源工具common-fileupload這個文件上
傳組件。這個common-fileupload上傳組件的jar包可以去apache官網上面下載,也可以在struts的lib文件夾下面找到,
struts上傳的功能就是基於這個實現的。common-fileupload是依賴於common-io這個包的,所以還需要下載這個包。
對於此包可以自己搜索,資源很多。
1.上傳文件邏輯
下面寫下邏輯層的代碼:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import javax.annotation.Resource;
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.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
HttpSession session = request.getSession();
String fileExtName = null;
String realSavePath = null;
String saveFilename = null;
int filesize = 0;
/*得到上傳文件的保存目錄,將上傳的文件存放於WEB-INF目錄下,不允許外界直接訪問,保證上傳文件的安全*/
String savePath = request.getSession().getServletContext().getRealPath("/WEB-INF/upload");
/*上傳時生成的臨時文件保存目錄*/
String tempPath = request.getSession().getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
/*創建臨時目錄*/
tmpFile.mkdir();
}
try{
/*使用Apache文件上傳組件處理文件上傳步驟:
1、創建一個DiskFileItemFactory工廠*/
DiskFileItemFactory factory = new DiskFileItemFactory();
/*設置工廠的緩衝區的大小,當上傳的文件大小超過緩衝區的大小時,就會生成一個臨時文件存放到指定的臨時目錄當中。*/
factory.setSizeThreshold(1024*100);
/*設置緩衝區的大小爲100KB,如果不指定,那麼緩衝區的大小默認是10KB
設置上傳時生成的臨時文件的保存目錄*/
factory.setRepository(tmpFile);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小爲:" + pContentLength + ",當前已處理:" + pBytesRead);
/**
*/
}
});
/**
解決上傳文件名的中文亂碼
*/
upload.setHeaderEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
/**
3、判斷提交上來的數據是否是上傳表單的數據
設置上傳單個文件的大小的最大值,目前是設置爲1024*1024字節,也就是1MB
*/
upload.setFileSizeMax(1024*1024*100);
/**設置上傳文件總量的最大值,最大值=同時上傳的多個文件的大小的最大值的和,目前設置爲10MB*/
upload.setSizeMax(1024*1024*1000);
/**4、使用ServletFileUpload解析器解析上傳數據,解析結果返回的是一個List<FileItem>集合,每一個FileItem對應一個Form表單的輸入項*/
List<FileItem> list = upload.parseRequest(request);
for(FileItem item:list){
filesize=(int) list.get(0).getSize();
/** filesize=parse(int)list.size();*/
/**如果fileitem中封裝的是普通輸入項的數據*/
if(item.isFormField()){
String name = item.getFieldName();
/**解決普通輸入項的數據的中文亂碼問題*/
String value = item.getString("UTF-8");
System.out.println(name + "=" + value);
}else{
String filename = item.getName();
if(filename==null || filename.trim().equals("")){
continue;
}
/**注意:不同的瀏覽器提交的文件名是不一樣的,有些瀏覽器提交上來的文件名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的文件名,如:1.txt
處理獲取到的上傳文件的文件名的路徑部分,只保留文件名部分*/
filename = filename.substring(filename.lastIndexOf("\\")+1);
/**得到上傳文件的擴展名*/
fileExtName = filename.substring(filename.lastIndexOf(".")+1);
/**如果需要限制上傳的文件類型,那麼可以通過文件的擴展名來判斷上傳的文件類型是否合法
獲取item中的上傳文件的輸入流*/
InputStream in = item.getInputStream();
/**得到文件保存的名稱*/
saveFilename = makeFileName(fileExtName);
/**得到文件的保存目錄*/
realSavePath = makePath(saveFilename, savePath);
/**創建一個文件輸出流*/
FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
/**創建一個緩衝區*/
byte buffer[] = new byte[1024];
/**判斷輸入流中的數據是否已經讀完的標識*/
int len = 0;
/** 循環將輸入流讀入到緩衝區當中,(len=in.read(buffer))>0就表示in裏面還有數據*/
while((len=in.read(buffer))>0){
/**使用FileOutputStream輸出流將緩衝區的數據寫入到指定的目錄(savePath + "\\" + filename)當中*/
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}
}catch (Exception e) {
e.printStackTrace();
}
return "**路徑**";
}
/**防止文件覆蓋的現象發生,要爲上傳文件產生一個唯一的文件名*/
private String makeFileName(String fileExtName){
Calendar c = Calendar.getInstance();
SimpleDateFormat df1 = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
String CurDatetime = df1.format(c.getTime());
String DOCID = CurDatetime + String.valueOf(Math.random()).substring(2, 4);
DOCID = DOCID.replace(":", "").replace(" ", "").replace("-", "");
return DOCID+"."+fileExtName;
}
/**
* 爲防止一個目錄下面出現太多文件,要使用hash算法打散存儲
*/
private String makePath(String filename,String savePath){
/**得到文件名的hashCode的值,得到的就是filename這個字符串對象在內存中的地址*/
int hashcode = filename.hashCode();
int dir1 = hashcode&0xf; //0--15
int dir2 = (hashcode&0xf0)>>4; //0-15
/**構造新的保存目錄*/
String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5
File file = new File(dir);
/**如果目錄不存在*/
if(!file.exists()){
file.mkdirs();
}
return dir;
}
以上就是上傳文件的主要邏輯代碼,樓樓是是以Spring+Springmvc+Mybatis爲框架進行搭建的項目工程。所以裏面有一些
屬於框架的東西。
2.下載文件邏輯
下面是下載的邏輯代碼:
/**下載附件*/
@RequestMapping("/DownFile")
public String DownFile(HttpServletRequest request,HttpServletResponse response,String upautor)
throws ServletException, IOException{
/**得到要下載的文件*/
String fileName = request.getParameter("upautor");
String realpath=request.getParameter("realpath");
String filetype =request.getParameter("filetype");
fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
String picgif="gif";
String picjpg="jpg";
String picpng="png";
String picbmp="bmp";
String redrect=null;
/**圖片的格式有(具體分析):
* gig tif rgb dib eps jpe pcx
得到要下載的文件*/
File file = new File(realpath + "\\" + fileName);
/**處理文件名*/
String realname = fileName.substring(fileName.indexOf("_")+1);
/**設置響應頭,控制瀏覽器下載該文件*/
/**判斷附件格式,如果爲圖片則顯示,否則下載*/
if(filetype.equals(picgif)||filetype.equals(picjpg)||filetype.equals(picpng)||filetype.equals(picbmp)){
response.setContentType(filetype);
response.setContentLength((int)file.length());
response.setHeader("Content-Disposition", "inline; filename="
+ URLEncoder.encode(realname, "UTF-8"));
InputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
long statistic = 0;
byte buffer[] = new byte[8192];
do {
int bytesRead = in.read(buffer);
if (bytesRead == -1)
break;
out.write(buffer, 0, bytesRead);
statistic = statistic + bytesRead;
out.flush();
} while (true);
in.close();
out.close();
redrect="redirect:/upload/showFile";
}else
{
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
/**讀取要下載的文件,保存到文件輸入流*/
FileInputStream in = new FileInputStream(realpath + "\\" + fileName);
/**創建輸出流*/
OutputStream out = response.getOutputStream();
/**創建緩衝區*/
byte[] buffer = new byte[1024];
int len = 0;
/**循環將輸入流中的內容讀取到緩衝區當中*/
while((len=in.read(buffer))>0){
response.setContentType("image/jpg");
response.setContentLength(buffer.length);
/**輸出緩衝區的內容到瀏覽器,實現文件下載*/
out.write(buffer, 0, len);
}
in.close();
out.close();
}
return "**路徑**";
}
通過以上可以在web工程中實現文件的上傳和下載,項目中是以圖片爲例,併爲其設置了格式的限制,修改對應需要自適應。