文件上传下载与String的一些知识点
文件上传
文件上传依赖apache的commons组件的commons-fileupload.jar和commons-io.jar包
pom.xml引入依赖
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
jsp代码
<%--
Created by IntelliJ IDEA.
User: 15002
Date: 2021/3/17
Time: 9:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="upload" enctype="multipart/form-data" method="post">
名字:<input type="text" name="username">
选择文件:<input type="file" name="file">
<input type="submit" value="提交">
</form>
</body>
</html>
Servlet代码
package com.yyb.servlet;
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.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;
/**
* @Author FuGwaaa
* @Date 2021/3/17 9:48
* @Version 1.0
*/
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
String realPath = this.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println("realPath"+realPath);
File file = new File(realPath);
System.out.println(file.exists());
if (!file.exists()&&!file.isDirectory()){
System.out.println("目录不存在");
file.mkdir();
}
try {
//1.创建DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.创建文件上传解析器
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//解决乱码
fileUpload.setHeaderEncoding("utf-8");
//判断是否为上传表单数据
if (!ServletFileUpload.isMultipartContent(request)) {
//按传统接收方式
System.out.println("传统传输方式");
return;
}
//3.解析器解析request对象
List<FileItem> fileItems = fileUpload.parseRequest(request);
for (FileItem item : fileItems) {
if (item.getFieldName().equals("username")){
String name = item.getFieldName();
String value = item.getString("utf-8");
System.out.println(name+":"+value);
}else{
String name = item.getName();
if (name==null||name.trim().equals("")){
continue;
}
String fileName = name.substring(name.lastIndexOf(File.separator) + 1);
InputStream is = item.getInputStream();
FileOutputStream os = new FileOutputStream(realPath + File.separator + fileName);
byte[] buffer = new byte[1024];
int len = 0;
while((len=is.read(buffer))>0){
os.write(buffer,0,len);
}
is.close();
os.close();
//删除处理文件上传时产生的临时文件
item.delete();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException {
this.doPost(request,response);
}
}
主要步骤如下:
1.创建工厂类DiskFileItemFactory对象:
DiskFileItemFactory factory = new DiskFileItemFactory() ;
2.使用工厂创建解析器对象:
ServletFileUpload fileUpload = new ServletFileUpload(factory) ;
3.使用解析器来解析request对象:
List list = fileUpload.parseRequest(request);
关于item.getFileName()与item.getName()
- getFileName()是获得字段名,比如:jsp表单的name(username)
- getName()是获得上传文件名,比如:上传文件时(a.txt)
文件上传总结
在这里刚开始犯了一个低级错误,在写Servlet时@WebServlet("/upload")忘写了**/,导致报错,经过很长时间的寻找发现是没有/**,在此记录希望以后不要再犯这样的低级错误。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN2XjlGcjAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL5VEVOBzYE1kMRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyQDN2UDN0ETM4EzMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
jsp页面在写的时候form表单的enctype属性要写为multipart/form-data;
this.getServletContext().getRealPath()
在写Servlet页面时想要获取到WEB-INF新建upload文件夹来存放上传的数据,
this.getServletContext().getRealPath()
这个方法是获得当前打包的WEB-INF的绝对路径,所以
this.getServletContext().getRealPath("/WEB-INF/upload")
的绝对路径为
E:\JAVA\self-study\fileUpload\out\artifacts\fileUpload_war_exploded\WEB-INF\upload
在这里我想总结下关于相对路径的知识,一般相对路径有三种写法分别为
./
,
/
,
../
-
代表访问本级目录下的文件,例如index.jsp要引用index.html就需要用到相对路径“./index.html”或者直接"index,html"./
-
代表访问上一级目录文件,例如register.html要引用login.html相对路径的写法为"…/login.html"../
-
代表访问根目录文件,就是最顶端的文件夹,注意这里例如register.html的根目录就为web,所以要引用index.jsp写法为"/index.jsp"/
关于mkdir()与mkdirs()方法
mkdir()方法创建文件夹时如果父目录不存在则不创建
mkdirs()方法创建文件夹时如果父目录不存在依旧创建,从不存在的文件夹开始创建创建多个文件夹
文件下载
fileList.jsp
<%--
Created by IntelliJ IDEA.
User: 15002
Date: 2021/3/18
Time: 10:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>文件列表</title>
</head>
<body>
<h1>点击下载</h1>
<c:forEach items="${list}" var="file">
<a href="downLoad?filename=${file.name}" target="_blank" rel="external nofollow" >${file.name}</a>
<br>
</c:forEach>
</body>
</html>
Servlet
package com.yyb.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.File;
import java.io.IOException;
/**
* @Author FuGwaaa
* @Date 2021/3/18 10:56
* @Version 1.0
*/
@WebServlet("/fileList")
public class FileListServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String realPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File file = new File(realPath);
File[] files = file.listFiles();
for (File f : files) {
System.out.println(f.getName());
}
request.setAttribute("list",files);
request.getRequestDispatcher("fileList.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
package com.yyb.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;
import java.net.URLEncoder;
/**
* @Author FuGwaaa
* @Date 2021/3/18 11:05
* @Version 1.0
*/
@WebServlet("/downLoad") public class DownLoadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String realPath = this.getServletContext().getRealPath("/WEB-INF/upload");
String filename = request.getParameter("filename");
File file = new File(realPath + File.separator + filename);
if (!file.exists()){
System.out.println("您要下载的文件已经被删除");
return;
}
//配置response头
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
FileInputStream fis = new FileInputStream(realPath + File.separator + filename);
ServletOutputStream os = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fis.read(buffer))>0){
os.write(buffer,0,len);
}
os.close();
fis.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
文件下载总结
文件上传时解析器解析requst对象,然后得到输入流,new输出流;而文件下载时new 输入流,然后配置response.setHeader,通过response得到输出流。
不管上传下载都会有
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fis.read(buffer))>0){
os.write(buffer,0,len);
}
记得关闭输入输出流
特别注意:idea中使用maven引入jar时如果要在WEB-INF/lib下用记得在项目配置的artifacts中的put into /WEB-INF/lib
关于String类的也在这里总结下
常用方法
返回值 | 方法名 | 作用 |
---|---|---|
int | length() | 得到一个字符串的字符个数(一个中文是一个字符,一个英文是一个字符,一个转义字符是一个字符) |
char[] | toCharArray() | 将一个字符串转换成字符数组 |
String[] | split(String) | 将一个字符串按照指定内容劈开 |
boolean | equals(String) | 判断两个字符串的内容是否一模一样 |
boolean | equalsIgnoreCase(String) | 忽略大小写的比较两个字符串的内容是否一模一样 |
boolean | contains(String) | 判断一个字符串里面是否包含指定的内容 |
boolean | startsWith(String) | 判断一个字符串是否以指定的内容开头 |
boolean | endsWith(String) | 判断一个字符串是否以指定的内容结尾 |
String | toUpperCase() | 将一个字符串全部转换成大写 |
String | toLowerCase() | 将一个字符串全部转换成小写 |
String | substring(int) | 从指定下标开始一直截取到字符串的最后 |
String | substring(int,int) | 从下标x截取到下标y-1对应的元素 |
String | trim() | 去除一个字符串的前后空格 |
int | indexOf(String) | 得到指定内容第一次出现的下标 |
int | lastIndexOf(String) | 得到指定内容最后一次出现的下标 |
String与new String()的区别
String s1 = "abc"
当常量池中没有”abc“字符串时在常量池中创建,返回给s1;如果有“abc”字符串对象,则直接返回给s1。
public class Test {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = s1;
System.out.println(s1==s2);
System.out.println(s1==s3);
}
}
运行结果
true
true
String s2 = new String("abc")
,如果常量池中没有“abc”字符串对象,则在常量池中创建,并且在堆中创建对象,返回地址给s2;如果常量池中有“abc“字符串对象,则直接在堆中创建对象,返回地址。
public class Test {
public static void main(String[] args) {
String s1 = "abc";
String s2 = new String("abc");
String s3 = new String("abc");
System.out.println(s1==s2);
System.out.println(s2==s3);
}
}
运行结果
false
false
池中创建,并且在堆中创建对象,返回地址给s2;如果常量池中有“abc“字符串对象,则直接在堆中创建对象,返回地址。
public class Test {
public static void main(String[] args) {
String s1 = "abc";
String s2 = new String("abc");
String s3 = new String("abc");
System.out.println(s1==s2);
System.out.println(s2==s3);
}
}
运行结果
false
false