使用Fileupload完成文件的上传下载
使用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完成文件的上传下载的更多相关文章
- JAVAWEB之文件的上传下载
文件上传下载 文件上传: 本篇文章使用的文件上传的例子使用的都是原生技术,servelt+jdbc+fileupload插件,这也是笔者的习惯,当接触到某些从未接触过的东西时,总是喜欢用最原始的东西将 ...
- 在Window的IIS中创建FTP的Site并用C#进行文件的上传下载
文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服务器计算机上. 然后,远程计算机可以使用 FTP ...
- 创建FTP的Site并用C#进行文件的上传下载
创建FTP的Site并用C#进行文件的上传下载 文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服 ...
- linux链接及文件互相上传下载
若排版紊乱可查看我的个人博客原文地址 基本操作 本篇博客主要介绍如何去链接远程的linux主机及如何实现本地与远程主机之间文件的上传下载操作,下面的linux系统是CentOS6.6 链接远程linu ...
- Spring实现文件的上传下载
背景:之前一直做的是数据库的增删改查工作,对于文件的上传下载比较排斥,今天研究了下具体的实现,发现其实是很简单.此处不仅要实现单文件的上传,还要实现多文件的上传. 单文件的下载知道了,多文件的下载呢? ...
- SocketIo+SpringMvc实现文件的上传下载
SocketIo+SpringMvc实现文件的上传下载 socketIo不仅可以用来做聊天工具,也可以实现局域网(当然你如果有外网也可用外网)内实现文件的上传和下载,下面是代码的效果演示: GIT地址 ...
- SSM框架之中如何进行文件的上传下载
SSM框架的整合请看我之前的博客:http://www.cnblogs.com/1314wamm/p/6834266.html 现在我们先看如何编写文件的上传下载:你先看你的pom.xml中是否有文件 ...
- python使用ftplib模块实现FTP文件的上传下载
python已经默认安装了ftplib模块,用其中的FTP类可以实现FTP文件的上传下载 FTP文件上传下载 # coding:utf8 from ftplib import FTP def uplo ...
- php文件夹上传下载控件分享
用过浏览器的开发人员都对大文件上传与下载比较困扰,之前遇到了一个php文件夹上传下载的问题,无奈之下自己开发了一套文件上传控件,在这里分享一下.希望能对你有所帮助. 以下是实例的部分脚本文件 这里我先 ...
随机推荐
- 示例讲解PostgreSQL表分区的三种方式
我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 表分区是解决一些因单表过大引用的性能问题的方式,比如某张表过大就会造成查询变慢,可能分区是一种解决方案.一般建议 ...
- 浅析C++的函数式编程
前言 Java8在Java中通过lambda表达式.Stream API引入了函数式编程,那么C++中是否也支持函数式编程呢?答案是肯定的.目前关于C++进行函数式编程的语法探究的相关博客.文章并不多 ...
- Python的字符串和编码
1. 字符编码 字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit) ...
- 7、基本数据类型(tuple)
7.1.tuple类: 1.元组元素用小括号括起来,用逗号分割每个元素,一般写元组的时候,推荐在最后加入逗号,该 逗号不占元素位置,目的是为了方便识别: tu = (111, "alex&q ...
- Vue $refs无法操作element-ui组件
比如我要操作这个dom元素↓↓↓ <el-badge :value="1" :max="99" class="message"> ...
- 严重:Exception sending context initialized event to listener instance of class [myJava.MyServletContextListener] java.lang.NullPointerException
以上错误是我在自定义Servlet监听器时遇到的,首先大致介绍一下我要实现的功能(本人刚开始学,如有错误,请多多指正): 为了统计网站访问量,防止服务器重启后,原访问次数被清零,因此自定义监听器类,实 ...
- String、StringBuilder和StringBuffer的比较
目录 1.String特性 1.1 不可变 1.2 字符串常量池 2.StringBuilder和StringBuffer 2.1 区别 2.2 应用场景 1.String特性 1.1 不可变 它是I ...
- 『动善时』JMeter基础 — 55、JMeter非GUI模式运行
目录 1.JMeter的非GUI模式说明 2.为什么使用非GUI模式运行JMeter 3.怎样使用非GUI模式运行JMeter (1)非GUI模式运行JMeter步骤 (2)其它参数说明 4.CLI模 ...
- 使用 VSCode 搭建 Flutter环境
概述 编辑器使用 vscode,不再安装 Android Studio. 安装 Git 点击这里 下载并安装 Git 配置 Java 环境 下载和安装 JDK 点击下载 Java SE Develop ...
- ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放
ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放 前言 加锁逻辑已经介绍完毕,那当一个线程重复加锁是如何处理的呢? 锁重入 在上一小节中,可以看到加锁的过程,再回头看 ...