学习进度条

JavaWeb图片上传功能学习总结

今日学习时间:1小时
今日代码量:100行
今日博客:1篇(JavaWeb实现图片上传的三种方式

一、核心知识点

  1. 前端表单配置
<!-- 必须设置enctype为multipart/form-data -->
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="imageFile" accept="image/*">
    <input type="submit" value="上传">
</form>
  1. 后端Servlet处理(使用Apache Commons FileUpload)
// 添加Maven依赖
// <dependency>
//     <groupId>commons-fileupload</groupId>
//     <artifactId>commons-fileupload</artifactId>
//     <version>1.4</version>
// </dependency>

@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        
        // 1. 检查请求是否包含文件
        if (!ServletFileUpload.isMultipartContent(request)) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        // 2. 配置上传参数
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setFileSizeMax(5 * 1024 * 1024); // 限制5MB

        try {
            // 3. 解析请求
            List<FileItem> items = upload.parseRequest(request);
            
            for (FileItem item : items) {
                if (!item.isFormField()) { // 是文件字段
                    String fileName = new File(item.getName()).getName();
                    String savePath = getServletContext().getRealPath("/uploads");
                    
                    // 4. 保存文件
                    File uploadDir = new File(savePath);
                    if (!uploadDir.exists()) uploadDir.mkdir();
                    
                    File storeFile = new File(savePath + File.separator + fileName);
                    item.write(storeFile);
                    
                    response.getWriter().print("上传成功: " + fileName);
                }
            }
        } catch (Exception ex) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }
}
  1. SpringMVC简化版(需配置MultipartResolver)
@Controller
public class ImageController {
    
    @PostMapping("/upload")
    public String handleUpload(@RequestParam("imageFile") MultipartFile file, 
                             Model model) throws IOException {
        
        if (!file.isEmpty()) {
            String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
            Path path = Paths.get("D:/uploads/" + fileName);
            Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
            model.addAttribute("msg", "上传成功: " + fileName);
        }
        return "result";
    }
}

二、关键配置

  1. web.xml添加限制(可选)
<servlet>
    <servlet-name>uploadServlet</servlet-name>
    <servlet-class>com.example.UploadServlet</servlet-class>
    <multipart-config>
        <max-file-size>5242880</max-file-size> <!-- 5MB -->
        <max-request-size>10485760</max-request-size> <!-- 10MB -->
    </multipart-config>
</servlet>
  1. SpringBoot配置(application.properties)
# 单个文件最大
spring.servlet.multipart.max-file-size=5MB
# 总请求最大
spring.servlet.multipart.max-request-size=10MB
# 临时存储路径
spring.servlet.multipart.location=/tmp

三、安全注意事项

  1. 文件名校验
String fileExt = fileName.substring(fileName.lastIndexOf("."));
if(!Arrays.asList(".jpg", ".png").contains(fileExt.toLowerCase())) {
    throw new IllegalArgumentException("只允许jpg/png格式");
}
  1. 防止目录穿越攻击
Path uploadPath = Paths.get("/safe/uploads").normalize();
Path filePath = uploadPath.resolve(fileName).normalize();
if(!filePath.startsWith(uploadPath)) {
    throw new IOException("非法文件路径");
}

四、今日实践成果

  1. 实现了原生Servlet文件上传功能
  2. 完成了SpringMVC版本的上传接口
  3. 添加了基础的文件类型校验
  4. 测试了不同尺寸图片的上传(<5MB成功,>5MB失败)

遇到的问题

  1. 中文文件名乱码(解决:添加request.setCharacterEncoding("UTF-8")
  2. 临时存储目录权限不足(解决:修改tomcat/conf/context.xml
  3. 重复文件名覆盖(解决:添加时间戳前缀)

明日计划

  1. 学习图片缩略图生成
  2. 实现多文件批量上传
  3. 研究云存储OSS方案

关键收获

  • 理解了multipart/form-data的原理
  • 掌握了文件流的基本操作
  • 认识了文件上传的安全风险点
posted @ 2025-04-17 20:18  haoyinuo  阅读(43)  评论(0)    收藏  举报