檔案上傳和下載
阿新 • • 發佈:2018-12-10
檔案的上傳和下載
檔案上傳
檔案上傳的三要素
- 提供form表單,method必須是post
- form表單的enctype必須是multipart/form-data
- 提供 input type = “file” 型別輸入
檔案上傳注意的細節
- 為保證伺服器安全,上傳檔案應該放在外界無法直接訪問的目錄下,比如放在WEB-INF下。
- 為了防止檔案覆蓋的現象發生,要為上傳的檔案產生一個唯一的檔名。
- 為防止一個目錄下出現太多檔案,要使用hash打亂演算法儲存
- 要限制上傳檔案的最大值
- 要限制上傳檔案的型別,在收到上傳檔名時,判斷後綴名是否合法
實現檔案上傳
1.編寫上傳頁面form表單
<form id="form1" action="${pageContext.request.contextPath }/upfileservlet" method="post" enctype="multipart/form-data">
使用者名稱:<input type="text" name="username" /><br>
電話:<input type="text" name="telphone" /><br>
檔案:<input type="file" name="file" /><br>
<input type="button" value="再新增一張圖片" onclick="addfile(this)"><br/>
<input type="submit" value="提交" />
</form>
<script type="text/javascript">
var num=2;
function addfile(obj){
//alert("xxx");
//dom操作
//新增div
var div1=document.createElement("div");
//新增input標籤
var inputfile=document.createElement("input");
inputfile.type="file";
inputfile.name="myfile"+num;
num++;
//新增刪除按鈕
var del=document.createElement("input");
del.type="button";
del.value="刪除";
del.onclick=function(){
this.parentNode.remove();
};
div1.append(inputfile);
div1.append(del);
var form1=document.getElementById("form1");
form1.insertBefore(div1,obj);
}
</script>
2.編寫servlet處理介面
/**
* 處理檔案上傳的方法
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 得到上傳路徑,將上傳的路徑放入WEB-INF下,不予許外界訪問,保證上傳檔案的安全性
String path = request.getServletContext().getRealPath("WEB-INF//upload");
File file = new File(path);
// 如果檔案不存在就建立
if (!file.exists()) {
file.mkdirs();
}
// 建立DiskFileItemFactory工廠
DiskFileItemFactory factory = new DiskFileItemFactory();
// 設定工廠緩衝大小
factory.setSizeThreshold(1024 * 100);// 預設為10K
// 設定上傳檔案的快取目錄
// factory.setRepository(repository);
// 建立一個檔案解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 解決中文亂碼問題
upload.setHeaderEncoding("utf-8");
// 監聽上傳檔案的進度
upload.setProgressListener(new ProgressListener() {
@Override
public void update(long arg0, long arg1, int arg2) {
System.out.println("檔案大小為:" + arg1 + ",當前已處理:" + arg0 + ",序號:" + arg2);
}
});
// 判斷提交的資料是不是表單資料
if (ServletFileUpload.isMultipartContent(request)) {
try {
// 設定上傳單個檔案的大小
upload.setFileSizeMax(1024 * 100);// 大小為100KB
// 設定所有檔案總量的最大值
upload.setSizeMax(1024 * 1024 * 10);// 大小為10M
// 解析資料,放回一個list集合,存放資料項
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
// 判斷是不是普通輸入項的資料
if (fileItem.isFormField()) {
// 獲得資料項的名字
String name = fileItem.getFieldName();
String value = fileItem.getString("utf-8");
System.out.println(name + "..." + value);
} else {// 封裝的是檔案
// 得到上傳檔案的名字
String name = fileItem.getName();
// 如果檔名為空
if (name == null || name.trim().equals("")) {
continue;
}
// 不同的瀏覽器傳入的名字可能存在路徑,解決檔名帶有路徑問題
String filename = name.substring(name.lastIndexOf("\\") + 1);
//控制檔案傳的型別
String ext = filename.substring(filename.lastIndexOf(".")+1);
if (!UUIDUtils.exts.contains(ext)) {
response.getWriter().write("檔案型別不支援");
return;
}
// 呼叫工具類,得到唯一標識
String fileName = UUIDUtils.getFileName(filename);
// 呼叫工具類,得到目錄
String newPath = UUIDUtils.makeFilePath(filename, path);
// 獲得輸入流
InputStream is = fileItem.getInputStream();
FileOutputStream fos = new FileOutputStream(newPath + "\\" + fileName);
// 寫入硬碟
byte[] bs = new byte[1024];
int len = 0;
while ((len = is.read(bs)) != -1) {
fos.write(bs, 0, len);
}
// 關流
fos.close();
is.close();
// 刪除檔案上傳時生成的臨時檔案
fileItem.delete();
System.out.println("檔案上傳成功");
}
}
} catch (FileUploadException e) {
e.printStackTrace();
System.out.println("檔案上傳失敗");
}
} else {
// 正常處理
// request.getParameter("username");
}
}
3.編寫工具類
/**
* uuid工具類
* @author 15216
*
*/
public class UUIDUtils {
//建立集合儲存檔案的型別
public static List<String> exts;
//靜態程式碼塊初始化檔案的型別
static {
exts = new ArrayList<String>();
//exts.add(".jpg");
exts.add(".png");
exts.add(".zip");
}
public static String getFileName(String filename) {
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
return uuid+"_"+filename;
}
public static String makeFilePath(String filename,String filepath) {
//得到字串的hascode值
int code = filename.hashCode();
//0x十六進位制字首
int dir1 = code&0xf;//得到後四位二進位制數
int code1 = code>>4;//右移四位
int dir2=code1&0xf;//得到後八位的前四位
String path = filepath+"\\"+dir1+"\\"+dir2;
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
return path;
}
}
servlet3.0支援的檔案上傳
程式碼實現
//註解配置檔案上傳的最大值
@MultipartConfig(fileSizeThreshold=1024*1024,maxFileSize=1024*100,maxRequestSize=1024*1024 )
/**
* servlet3.0
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設定編碼
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//獲取路徑
String path = request.getServletContext().getRealPath("WEB-INF//upload");
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
//接收資料
Collection<Part> parts = request.getParts();
if (parts!=null) {
for (Part part : parts) {
//獲取檔名
String fileName = part.getSubmittedFileName();
//如果為空不是檔案
if (fileName!=null) {//是檔案
if (fileName.trim().equals("")) {
continue;
}
//form-data; name="myfile1"; filename="D:\圖片\timg.jpg"
String header = part.getHeader("content-disposition");
System.out.println(header);
String name1 = header.split("; ")[2];//filename="D:\圖片\timg.jpg"
System.out.println(name1);//"D:\圖片\timg.jpg"
String name2 = name1.substring(name1.indexOf("\"")+1, name1.length()-1);
fileName = name2.substring(name2.lastIndexOf("\\")+1);
System.out.println(fileName);
//為檔名產生一個唯一標識
String filename = UUIDUtils.getFileName(fileName);
String filepath = UUIDUtils.makeFilePath(filename, path);
part.write(filepath+"\\"+filename);
System.out.println("檔案上傳成功");
}else {
//獲取普通資料的名字
String name = part.getName();
String value = request.getParameter(name);
System.out.println(name+"..."+value);
}
}
}
}
檔案下載
思想:首先需要編寫一個ListFileServleDt列出檔案目錄下的所有的檔案,在jsp檔案中提供超連結的方式給使用者進行下載操作,然後編寫DownServlet實現下載操作。
編寫ListFileServlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取檔案路徑
String path = request.getServletContext().getRealPath("WEB-INF//upload");
File file = new File(path);
Map<String, String> map = new HashMap<String, String>();
listFile(file, map);
//將集合放入request中
request.setAttribute("map", map);
//轉發到列表jsp,資料不會丟失
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
}
/**
* 通過遞迴將目標目錄下的檔案全部存到map集合中
* @param dir
* @param map
*/
public void listFile(File dir,Map<String, String> map) {
File[] files = dir.listFiles();
if (files!=null) {
for (File file : files) {
//判斷是不是目錄
if (file.isDirectory()) {
listFile(file, map);
}else {
//得到檔案的名字
String uuid_name = file.getName();//uuid_xxx.jpg
//擷取檔案的名字
String realname = uuid_name.substring(uuid_name.indexOf("_")+1);
//將得到檔案的名字作為key值,將realname作為值存入集合
map.put(uuid_name, realname);
}
}
}
}
編寫listfile.jsp頁面
<body>
<h2>下載</h2>
<c:forEach items="${map }" var="entry">
<!-- 建立一個地址,並放入域中 1、URL重寫2、中文編碼 -->
<c:url var="myurl" value="/downfileservlet">
<c:param name="filename" value="${entry.key }"></c:param>
</c:url>
${entry.value } <a href="${myurl }">下載</a>
</c:forEach>
</body>
編寫downFileServlet
/**
* 檔案下載
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設定編碼
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//接收要下載的檔名
String filename = request.getParameter("filename");
//得到路徑名
String path = request.getServletContext().getRealPath("WEB-INF//upload");
if (filename==null||filename.trim().equals("")) {
return;
}
//獲取檔案在upload中的位置
String name = filename.substring(filename.indexOf("_")+1);
//傳入的是包含唯一編碼的檔名
String filepath = UUIDUtils.makeFilePath(filename, path);
File file = new File(filepath+"\\"+filename);
System.out.println(file);
if (!file.exists()) {
response.getWriter().write("檔案不存在");
return;
}
//設定頭
response.setHeader("content-disposition", "attachment;filename"+URLDecoder.decode(name,"utf-8"));
ServletOutputStream os = response.getOutputStream();
FileInputStream fis = new FileInputStream(file);
int len = 0;
byte[] bs = new byte[1024];
while((len = fis.read(bs))!=-1) {
os.write(bs,0,len);
}
fis.close();
}