首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JavaWeb 文件上傳下載完整實戰指南

     編輯:Java 相關知識

基礎上傳範例

JSP 表單

<form action="${pageContext.request.contextPath}/UploadServlet" 
      enctype="multipart/form-data" method="post">
    上傳用戶:<input type="text" name="username" /><br/>
    上傳文件1:<input type="file" name="file1" /><br/>
    上傳文件2:<input type="file" name="file2" /><br/>
    <input type="submit" value="上傳" />
</form>

Servlet 核心邏輯

DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);

if (!upload.isMultipartContent(request)) return;

List<FileItem> list = upload.parseRequest(request);
for (FileItem item : list) {
    if (item.isFormField()) {
        // 普通欄位
        String value = item.getString("UTF-8");
    } else {
        // 文件欄位
        String filename = item.getName().substring(item.getName().lastIndexOf("\\") + 1);
        InputStream in = item.getInputStream();
        // 寫入文件...
    }
}

生產級上傳增強功能

功能實現方式
中文檔名亂碼 upload.setHeaderEncoding("UTF-8")
安全存儲路徑 文件存放於 WEB-INF/upload 等外部不可直接訪問目錄
防止文件覆蓋 生成唯一文件名:UUID.randomUUID().toString() + "_" + 原檔名
目錄分散存儲 雜湊算法打散:hashCode & 0xF 兩級子目錄
限制單文件大小 upload.setFileSizeMax(1024 * 1024 * 10) (10MB)
限制總上傳大小 upload.setSizeMax(1024 * 1024 * 100) (100MB)
文件類型驗證 檢查副檔名白名單
上傳進度監聽 實作 ProgressListener 介面
動態增加上傳欄位 JavaScript createElement("input") 動態添加

完整上傳 Servlet 關鍵代碼

public class UploadServlet1 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        String savePath = getServletContext().getRealPath("/WEB-INF/upload");
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setRepository(new File(getServletContext().getRealPath("/WEB-INF/temp")));
        
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setHeaderEncoding("UTF-8");
        upload.setFileSizeMax(1024 * 1024 * 10);
        
        List<FileItem> list = upload.parseRequest(request);
        for (FileItem item : list) {
            if (item.isFormField()) {
                String value = item.getString("UTF-8");
            } else {
                String filename = makeFileName(item.getName());
                String realPath = makePath(filename, savePath);
                // 寫入文件流...
                item.delete(); // 刪除臨時文件
            }
        }
    }
    
    private String makeFileName(String filename) {
        return UUID.randomUUID().toString() + "_" + filename.substring(filename.lastIndexOf("\\") + 1);
    }
    
    private String makePath(String filename, String savePath) {
        int hash = filename.hashCode();
        int d1 = hash & 0xF;
        int d2 = (hash & 0xF0) >> 4;
        String dir = savePath + "\\" + d1 + "\\" + d2;
        new File(dir).mkdirs();
        return dir;
    }
}

文件下載實現

列出可下載文件

public class ListFileServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        String filepath = getServletContext().getRealPath("/WEB-INF/upload");
        Map<String, String> map = new HashMap<>();
        listFiles(new File(filepath), map);
        request.setAttribute("map", map);
        request.getRequestDispatcher("/listfile.jsp").forward(request, response);
    }
    
    private void listFiles(File file, Map<String, String> map) {
        if (file.isDirectory()) {
            for (File f : file.listFiles()) listFiles(f, map);
        } else {
            String realName = file.getName().substring(file.getName().indexOf("_") + 1);
            map.put(file.getName(), realName);
        }
    }
}

JSP 顯示下載連結

<c:forEach var="me" items="${map}">
    <c:url value="/servlet/DownLoadServlet" var="downurl">
        <c:param name="filename" value="${me.key}"/>
    </c:url>
    ${me.value} <a href="${downurl}">下載</a><br/>
</c:forEach>

下載 Servlet

public class DownLoadServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        String filename = request.getParameter("filename");
        filename = new String(filename.getBytes("ISO-8859-1"), "UTF-8");
        
        String path = makePath(filename, getServletContext().getRealPath("/WEB-INF/upload"));
        File file = new File(path + "\\" + filename);
        
        String realName = filename.substring(filename.indexOf("_") + 1);
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realName, "UTF-8"));
        
        // 流式傳輸...
    }
}

最佳實踐總結

  • 上傳文件統一存放於 WEB-INF 受保護目錄
  • 使用 UUID + 雜湊目錄防止衝突與效能下降
  • 下載時透過 Content-Disposition: attachment 強制瀏覽器彈出下載框
  • 中文檔名需經 URLEncoder.encode 處理
  • 大文件採用緩衝流分塊讀寫,避免 OOM
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved