文件的上传
新建项目myfile
1. JSP部分
上传一张图片
- 在web下新建upload.jsp文件,设置两个按钮,一个点击时会选择图片,另一个对图片进行提交
(1)form表单的method设置为post(设置为post意味着在Servlet类中要重写doPost方法),若设置为get(重写doGet方法)则只会将文件名传给服务端,而不是文件本身
(2)form表单的enctype设置为multipart/form-data,以二进制的形式传输数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form enctype="multipart/form-data" action="upload" method="post">
//action后的"upload"表示我们将通过它与Servlet进行关联,注意不要将“upload”写为"/upload"
<input type="file" name="img" /><br/>
//定义第一个按钮,按钮类型为file类型,点击后可以选择选择图片
<input type="submit" name="上传"/>
//定义第二个按钮,按钮类型为submit,该类型的按钮可以将form表单提交
</form>
</body>
</html>
- 定义Servlet文件
在src下新建包,包下新建java类UploadServlet,接收JSP中传来的图片
package com.shunde.file;
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.IOException;
import java.io.InputStream;
@WebServlet("/upload") //与jsp关联起来
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
String img = req.getParameter("img");
从客户端接收数据到服务端使用getParameter方法 从服务端接收数据到服务端使用getAttribute方法
但是在这里我们不能使用getParameter方法,因为这个方法接收的是一个字符串,而我们传图片或者文件时,都使用流的方式
*/
InputStream inputStream = req.getInputStream(); //读取从客户端传来的流
//取出流中的内容
int temp = 0;
while((temp = inputStream.read()) != -1){ //读取流inputStream中的内容到temp中,直到返回-1(返回-1代表流中的内容已经读完)
System.out.println(temp);
}
}
}
- 编译运行,选择图片,点击上传,查看IDEA内的打印信息
表示图片已经传输到服务端了 - 上传一个TXT文件
点击上传一个txt文件后,仍然显示的是一串数字 - 通过输入流获取客户端传来的数据流
将上面的字节流转换为字符流,再将字符流转换为缓冲字符流
修改代码
package com.shunde.file;
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.*;
@WebServlet("/upload") //与jsp关联起来
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
/*
String img = req.getParameter("img");
从客户端接收数据到服务端使用getParameter方法 从服务端接收数据到服务端使用getAttribute方法
但是在这里我们不能使用getParameter方法,因为这个方法接收的是一个字符串,而我们传图片或者文件时,都使用流的方式
*/
InputStream inputStream = req.getInputStream(); //读取从客户端传来的字节流
Reader reader = new InputStreamReader(inputStream); //将字节流转换为字符流
BufferedReader bufferedReader = new BufferedReader(reader); //将字符流转换为缓冲字符流
// //取出字节流中的内容
// int temp = 0;
// while((temp = inputStream.read()) != -1){ //读取流inputStream中的内容到temp中,直到返回-1(返回-1代表流中的内容已经读完)
// System.out.println(temp);
// }
//读取缓冲字符流中的内容
String str = " ";
while ((str = bufferedReader.readLine()) != null){
System.out.println(str);
}
}
}
- 通过输出流将数据流输出到本地硬盘
在项目目录下新建一个文件file,将客户端传来的数据保存到file目录下
package com.shunde.file;
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.*;
@WebServlet("/upload") //与jsp关联起来
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//req.setCharacterEncoding("UTF-8");
/*
String img = req.getParameter("img");
从客户端接收数据到服务端使用getParameter方法 从服务端接收数据到服务端使用getAttribute方法
但是在这里我们不能使用getParameter方法,因为这个方法接收的是一个字符串,而我们传图片或者文件时,都使用流的方式
*/
InputStream inputStream = req.getInputStream(); //读取从客户端传来的字节流
Reader reader = new InputStreamReader(inputStream); //将字节流转换为字符流
BufferedReader bufferedReader = new BufferedReader(reader); //将字符流转换为缓冲字符流
// //取出字节流中的内容
// int temp = 0;
// while((temp = inputStream.read()) != -1){ //读取流inputStream中的内容到temp中,直到返回-1(返回-1代表流中的内容已经读完)
// System.out.println(temp);
// }
//获取文件夹file的绝对路径
String path = req.getServletContext().getRealPath("file/copy1.txt");
OutputStream outputStream = new FileOutputStream(path);//创建输出字节流,传入地址
Writer writer = new OutputStreamWriter(outputStream); //将输出字节流转换为输出字符流
BufferedWriter bufferedWriter = new BufferedWriter(writer);//将输出字符流转换为输出缓冲字符流
//读取缓冲字符流中的内容
String str = " ";
while ((str = bufferedReader.readLine()) != null){
bufferedWriter.write(str);
}
//关闭流
bufferedWriter.close();
writer.close();
outputStream.close();
bufferedReader.close();
reader.close();
inputStream.close();
}
}
- 编译运行
上传1.txt文件
就会将1.txt文件中的内容保存至copy1.txt文件 - 打开copy1.txt文件
问题1:在copy1.txt文件中多了1.txt文件中没有的内容
问题2:不会自动换行
fileupload组件的使用
fileupload组件可以将所有的请求信息都解析成Fileteam对象,可以通过Fileteam对象的操作完成上传
- 下载两个jar包
(1)commons-io.jar
(2)commons-fileupload.jar
在项目的WEB-INF目录下新建目录lib,将两个包复制到里面
- 在upload.jsp文件中加入一行代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form enctype="multipart/form-data" action="upload" method="post">
<%-- action后的"/upload"表示我们将通过它与Servlet进行关联,--%>
<input type="text" name="txt"/><br/>
<input type="file" name="img" /><br/>
<%-- //定义第一个按钮,按钮类型为file类型,点击后可以选择选择图片--%>
<input type="submit" name="上传"/>
<%-- //定义第二个按钮,按钮类型为submit,该类型的按钮可以将form表单提交--%>
</form>
</body>
</html>
- 重写UploadServlet类
将用户上传的数据转换成一个FileItem对象,我们可以通过对这个对象操作
package com.shunde.file;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.Servlet;
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.*;
import java.util.List;
@WebServlet("/upload") //与jsp关联起来
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//req.setCharacterEncoding("UTF-8");
/*
String img = req.getParameter("img");
从客户端接收数据到服务端使用getParameter方法 从服务端接收数据到服务端使用getAttribute方法
但是在这里我们不能使用getParameter方法,因为这个方法接收的是一个字符串,而我们传图片或者文件时,都使用流的方式
*/
// InputStream inputStream = req.getInputStream(); //读取从客户端传来的字节流
// Reader reader = new InputStreamReader(inputStream); //将字节流转换为字符流
// BufferedReader bufferedReader = new BufferedReader(reader); //将字符流转换为缓冲字符流
// //取出字节流中的内容
// int temp = 0;
// while((temp = inputStream.read()) != -1){ //读取流inputStream中的内容到temp中,直到返回-1(返回-1代表流中的内容已经读完)
// System.out.println(temp);
// }
// //获取文件夹file的绝对路径
// String path = req.getServletContext().getRealPath("file/copy1.txt");
// OutputStream outputStream = new FileOutputStream(path);//创建输出字节流,传入地址
// Writer writer = new OutputStreamWriter(outputStream); //将输出字节流转换为输出字符流
// BufferedWriter bufferedWriter = new BufferedWriter(writer);//将输出字符流转换为输出缓冲字符流
//
// //读取缓冲字符流中的内容
// String str = " ";
// while ((str = bufferedReader.readLine()) != null){
// System.out.println(str);
// bufferedWriter.write(str);
// }
//关闭流
// bufferedWriter.close();
// writer.close();
// outputStream.close();
// bufferedReader.close();
// reader.close();
// inputStream.close();
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
try {
List<FileItem> list = servletFileUpload.parseRequest(req); //从req中的数据流转换为FileItem类型集合list
//遍历list
for(FileItem fileItem : list){
if(fileItem.isFormField()){ //如果传来的数据流是普通类型,即不是file类型
String name = fileItem.getFieldName(); //获得这个普通类型数据流的名称,这个名称是我们在jsp文件中自定义的
String value = fileItem.getString("UTF-8"); //设置编码格式
System.out.println(name + ":" + value); //输出名称以及内容
}else{ //如果是file类型
String filename = fileItem.getFieldName(); //获得数据流的名称,在jsp文件中定义
long size = fileItem.getSize(); //获得数据流的size
System.out.println(filename + ":" + size + "Byte");
InputStream inputStream = fileItem.getInputStream(); //将fileItem中的内容送入到输入流中
String path = req.getServletContext().getRealPath("file/" + filename); //获得真实路径
OutputStream outputStream = new FileOutputStream(path); //获得输出流
int temp = 0;
while ((temp = inputStream.read()) != -1){ //遍历,将输出流中的内容写入文件中
outputStream.write(temp);
}
outputStream.close();
inputStream.close();
System.out.println("上传成功");
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
- 编译运行
输入内容选择文件,点击上传
文件下载
新建项目myFileDownload
- index.jsp内代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="download">1.png</a>
</body>
</html>
- 定义DownloadServlet类
package com.shunde.file;
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.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应方式
resp.setContentType("applicationg/x-msdownload"); //启动下载器(固定语句,必须这样写)
String filename = "1.jpg"; //设置下载之后的文件名
resp.setHeader("Content-Disposition","attachment;filename=" + filename);
//以上三行代码都是固定了,我们只需要更改下载之后的文件名
//获取输出流输入流
OutputStream outputStream = resp.getOutputStream(); //从resp中获取输出流
String path = req.getServletContext().getRealPath("1.jpg"); //获得图片的资源
FileInputStream fileInputStream = new FileInputStream(path); //将图片送入到输入流中
//读取输入流中的内容到temp中,再把temp写入到输出流中
int temp = 0;
while((temp = fileInputStream.read()) != -1){ //将输入流中的内容写入到temp中
outputStream.write(temp); //再将temp中的内容写入到输出流中
}
fileInputStream.close();
outputStream.close();
}
}
- 在web目录下新建img文件,复制一张图片进去