使用Fileupload完成文件的上传下载

为什么需要进行文件上传下载?

因为需要让用户能够访问服务器上的文件资源

引入jar包

文件上传

注意事项

  • form表单的提交方式必须为post(因为get能够提交的数据量太小)
  • form表单的 enctype属性必须为:"multipart/form-data",以二进制方式传输表单数据
  • 需要提交的文件需要设置input的属性为file,必须设置name属性,否则无法被提交

编写一个简单的文件上传jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<base href="<%=request.getContextPath() + "/"%>">
</head>
<body>
<form action="upload/demo" enctype="multipart/form-data" method="post">
<p>
姓名:<input type="text" name="sname" />
</p>
<p>
年龄:<input type="number" name="age" />
</p>
<p>
请你上传你的头像:<input type="file" name="photo" /> <br>
<span style="color: red">${requestScope.errorMsg}</span>
</p>
<p>
<input type="submit" value="提交">
</p>
</form>
</body>
</html>

编写Servlet

Student类用于封装数据,后期展示用到

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable; @Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {
private Integer sid;
private String sname;
private Integer age;
private String fileName;
private String fileType;
}

Servlet处理文件上传

package com.oa.servlet;

import com.oa.entity.Student;
import com.oa.service.StudentService;
import com.oa.service.impl.StudentServiceImpl;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID; @WebServlet("/upload/demo")
public class UploadDemoServlet extends HttpServlet {
private StudentService studentService = new StudentServiceImpl(); @Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
// 定义一个学生实体的属性
String sname = "";
int age = 0;
String realFilename = "";
String fileType = ""; try {
// 生产FileItem的工厂类
DiskFileItemFactory factory = new DiskFileItemFactory();
// 实现上传操作的类
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
// 设置headerEncoding为UTF-8。这样可以解决上传的文件中文名问题
servletFileUpload.setHeaderEncoding("utf-8");
// servletFileUpload.setFileSizeMax(1024 * 20);// 设置文件最大上传大小为20k,如果超过直接抛出异常
// 获得到所有的表单项
List<FileItem> list = servletFileUpload.parseRequest(req);
// 遍历所有的表单项
for (FileItem fileItem : list) {
// 不是一个表单字段,表示为一个文件
if(!fileItem.isFormField()) {
// 判断文件格式
String filename = fileItem.getName();
fileType = filename.substring(filename.lastIndexOf("."));
if (!(".jpg".equals(fileType) || ".png".equals(fileType) || ".gif".equals(fileType))) {
req.setAttribute("errorMsg","文件格式不正确");
req.getRequestDispatcher("/fileuploadDemo.jsp").forward(req, resp);
return;
}
// 判断文件大小是否大于50k,这里的单位是字节
if (fileItem.getSize() > (1024 * 50)) {
req.setAttribute("errorMsg","图片大小最大为50k");
req.getRequestDispatcher("/fileuploadDemo.jsp").forward(req, resp);
return;
}
// 获得服务器的部署路径下的/imgs目录
String servletPath = this.getServletContext().getRealPath("/imgs");
File imgsDir = new File(servletPath);
// 如果文件夹不存在,就创建
if(!imgsDir.exists()) {
imgsDir.mkdirs();
}
// 最后存储在服务器上的文件名
realFilename = UUID.randomUUID().toString() + fileType;
// 写入到服务器中
fileItem.write(new File(imgsDir, realFilename));
}
// 这个时候就代表是字段
else {
if ("sname".equals(fileItem.getFieldName())){
// 这里以为UTF-8的格式获取数据
sname = fileItem.getString("utf-8");
}
if ("age".equals(fileItem.getFieldName())) {
age = Integer.parseInt(fileItem.getString());
}
}
}
// 封装Student对象存入数据库
Student student = new Student(null, sname, age, realFilename, fileType);
studentService.save(student); } catch (Exception e) {
e.printStackTrace();
}
}
}

文件上传后可以在服务器的部署目录中看到一个imgs的目录,其中就是上传的图片

文件上传会遇到的一些问题解析

  • 接收到的文件为中文名称时乱码
第1种解决方案:request.setCharacterEncoding("UTF-8");
第2种解决方案:
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
servletFileUpload.setHeaderEncoding("utf-8");
  • 接收普通文本字段数据时发生乱码
// FileItem在获取数据时,指定编码
fileItem.getString("utf-8");
  • 限定文件上传的格式(不完善,使用cpdetector插件可以精确判断)
// 先获取到文件的名称
String filename = fileItem.getName();
// 获取到文件的后缀
fileType = filename.substring(filename.lastIndexOf("."));
// 判断后缀
if (!(".jpg".equals(fileType)){}
  • 限定文件上传的大小
// 第一种方式,如果超出大小会直接抛出异常(不推荐)
servletFileUpload.setFileSizeMax(1024 * 20);// 设置文件最大上传大小为20k // 第二种方式
if (fileItem.getSize() > (1024 * 50)) {
req.setAttribute("errorMsg","图片大小最大为50k");
req.getRequestDispatcher("/fileuploadDemo.jsp").forward(req, resp);
return;
}
  • 指定不到服务器的路径
// 使用getReal获取服务器的绝对路径,这里是获取部署路径下的下一级目录imgs
this.getServletContext().getRealPath("/imgs");
File imgsDir = new File(servletPath);
  • 指定的文件目录不存在
// 如果文件夹不存在,就创建
if(!imgsDir.exists()) {
imgsDir.mkdirs();
}
  • 文件名重复如何解决?
// 使用UUID + 文件后缀的方式
String realFileName = UUID.randomUUID().toString() + fileType;

文件下载

编写一个jsp文件用于student表数据的展示

  • (这个表在前面文件上传的时候可以看到JavaBean)
  • 这个数据写个Servlet解决就可以了
<body>
<table border="1px red solid" cellspacing="0" cellpadding="2px">
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>头像图片名称</th>
<th>图片格式</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%-- 这里放你自己的数据 --%>
<c:forEach items="${requestScope.pageInfo.list}" var="student">
<tr>
<td>${student.sid}</td>
<td>${student.sname}</td>
<td>${student.age}</td>
<td><img width="160px" src="imgs/${student.fileName}" alt="" /></td>
<td>${student.fileType}</td>
<td><a href="download/demo?fileName=${student.fileName}&fileType=${student.fileType}">下载头像图片</a></td>
</tr>
</c:forEach>
</tbody>
</table>
</body>

编写Servlet完成文件下载功能

import org.apache.commons.io.IOUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; @WebServlet("/download/demo")
public class DownLoadServlet extends HttpServlet { @Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取需要下载的文件名及其类型
String filename = req.getParameter("fileName");
String fileType = req.getParameter("fileType");
// 设置响应头,文件下载名称
resp.setHeader("Content-Disposition", "attachment; filename=" + filename);
// 设置响应的格式
resp.setContentType(fileType); // 获取当前文件在服务器中的路径
String realPath = this.getServletContext().getRealPath("/imgs");
File file = new File(realPath, filename);
if (file.exists()) {
// 获得该文件的输入流
FileInputStream fis = new FileInputStream(file);
// 相应给客户端
IOUtils.copy(fis, resp.getOutputStream());
// 关闭资源
fis.close();
}
}
}

使用Fileupload完成文件的上传下载的更多相关文章

  1. JAVAWEB之文件的上传下载

    文件上传下载 文件上传: 本篇文章使用的文件上传的例子使用的都是原生技术,servelt+jdbc+fileupload插件,这也是笔者的习惯,当接触到某些从未接触过的东西时,总是喜欢用最原始的东西将 ...

  2. 在Window的IIS中创建FTP的Site并用C#进行文件的上传下载

    文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服务器计算机上. 然后,远程计算机可以使用 FTP ...

  3. 创建FTP的Site并用C#进行文件的上传下载

    创建FTP的Site并用C#进行文件的上传下载 文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服 ...

  4. linux链接及文件互相上传下载

    若排版紊乱可查看我的个人博客原文地址 基本操作 本篇博客主要介绍如何去链接远程的linux主机及如何实现本地与远程主机之间文件的上传下载操作,下面的linux系统是CentOS6.6 链接远程linu ...

  5. Spring实现文件的上传下载

    背景:之前一直做的是数据库的增删改查工作,对于文件的上传下载比较排斥,今天研究了下具体的实现,发现其实是很简单.此处不仅要实现单文件的上传,还要实现多文件的上传. 单文件的下载知道了,多文件的下载呢? ...

  6. SocketIo+SpringMvc实现文件的上传下载

    SocketIo+SpringMvc实现文件的上传下载 socketIo不仅可以用来做聊天工具,也可以实现局域网(当然你如果有外网也可用外网)内实现文件的上传和下载,下面是代码的效果演示: GIT地址 ...

  7. SSM框架之中如何进行文件的上传下载

    SSM框架的整合请看我之前的博客:http://www.cnblogs.com/1314wamm/p/6834266.html 现在我们先看如何编写文件的上传下载:你先看你的pom.xml中是否有文件 ...

  8. python使用ftplib模块实现FTP文件的上传下载

    python已经默认安装了ftplib模块,用其中的FTP类可以实现FTP文件的上传下载 FTP文件上传下载 # coding:utf8 from ftplib import FTP def uplo ...

  9. php文件夹上传下载控件分享

    用过浏览器的开发人员都对大文件上传与下载比较困扰,之前遇到了一个php文件夹上传下载的问题,无奈之下自己开发了一套文件上传控件,在这里分享一下.希望能对你有所帮助. 以下是实例的部分脚本文件 这里我先 ...

随机推荐

  1. 示例讲解PostgreSQL表分区的三种方式

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 表分区是解决一些因单表过大引用的性能问题的方式,比如某张表过大就会造成查询变慢,可能分区是一种解决方案.一般建议 ...

  2. 浅析C++的函数式编程

    前言 Java8在Java中通过lambda表达式.Stream API引入了函数式编程,那么C++中是否也支持函数式编程呢?答案是肯定的.目前关于C++进行函数式编程的语法探究的相关博客.文章并不多 ...

  3. Python的字符串和编码

    1. 字符编码 字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit) ...

  4. 7、基本数据类型(tuple)

    7.1.tuple类: 1.元组元素用小括号括起来,用逗号分割每个元素,一般写元组的时候,推荐在最后加入逗号,该 逗号不占元素位置,目的是为了方便识别: tu = (111, "alex&q ...

  5. Vue $refs无法操作element-ui组件

    比如我要操作这个dom元素↓↓↓ <el-badge :value="1" :max="99" class="message"> ...

  6. 严重:Exception sending context initialized event to listener instance of class [myJava.MyServletContextListener] java.lang.NullPointerException

    以上错误是我在自定义Servlet监听器时遇到的,首先大致介绍一下我要实现的功能(本人刚开始学,如有错误,请多多指正): 为了统计网站访问量,防止服务器重启后,原访问次数被清零,因此自定义监听器类,实 ...

  7. String、StringBuilder和StringBuffer的比较

    目录 1.String特性 1.1 不可变 1.2 字符串常量池 2.StringBuilder和StringBuffer 2.1 区别 2.2 应用场景 1.String特性 1.1 不可变 它是I ...

  8. 『动善时』JMeter基础 — 55、JMeter非GUI模式运行

    目录 1.JMeter的非GUI模式说明 2.为什么使用非GUI模式运行JMeter 3.怎样使用非GUI模式运行JMeter (1)非GUI模式运行JMeter步骤 (2)其它参数说明 4.CLI模 ...

  9. 使用 VSCode 搭建 Flutter环境

    概述 编辑器使用 vscode,不再安装 Android Studio. 安装 Git 点击这里 下载并安装 Git 配置 Java 环境 下载和安装 JDK 点击下载 Java SE Develop ...

  10. ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放

    ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放 前言 加锁逻辑已经介绍完毕,那当一个线程重复加锁是如何处理的呢? 锁重入 在上一小节中,可以看到加锁的过程,再回头看 ...