文件的上传和下载
文件的上传
* 文件上传:将客户端的文件 保存到服务器端
* 对表单限制:
1.提交方式 method 必须为 post
2.表单的属性 enctype必须为 : multipart/form-data
* enctype:指表单发送数据的编码方式
* application/x-www-form-urlencoded:数据进行URL编码
* text/plain:纯文本发送
* multipart/form-data:可以发送二进制数据,专门用于文件上传
* 对Servlet限制:
1.request.getParameter()方法不能使用了。即使用了也获取的是null
2.使用request.getInputStream()来获取所有消息体数据。然后解析
* 解析消息体数据:
* 使用 commons-fileupload 组件解析消息体
* 步骤:
1.导入jar包。注意:还需要导入 commons-io.jar
2.创建解析器工厂
3.获取解析器
4.解析request对象,返回 List<FileItem> (表单项对象集合)
5.遍历集合,获取每一个表单项,获取数据
* FileItem对象的方法:
* 通用方法:
* 判断是否是普通表单项:isFormField()
* 获取表单项name名称:getFieldName()
* 普通表单项的方法:
* 获取表单项的值:getString(String encoding)
* 文件表单项的方法:
* 获取文件名称:getName()
* 获取文件类型:getContentType()
* 获取文件大小:getSize()
* 获取文件关联的输出流:getOutputStream()
* 将文件数据写入硬盘:write(File file)
@WebServlet(name = "UpLoadServlet",value = "/upload")
public class UpLoadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
try {
request.setCharacterEncoding("utf-8");
String realPath = this.getServletContext().getRealPath("/upload");
File file = new File(realPath);
if (!file.exists()){
file.mkdirs();
}
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
List<FileItem> list = servletFileUpload.parseRequest(request);
for (FileItem fileItem : list) {
if (fileItem.isFormField()){
String fieldName = fileItem.getFieldName();
String string = fileItem.getString("utf-8");
System.out.println(fieldName);
System.out.println(string);
}else {
String name = fileItem.getName();
String contentType = fileItem.getContentType();
long size = fileItem.getSize();
name=name+ UUID.randomUUID().toString().replace("-","");
OutputStream outputStream = fileItem.getOutputStream();
File file1 = new File(file, name);
fileItem.write(file1);
System.out.println("上传的文件在"+file1.getAbsolutePath());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
文件的下载
文件下载:服务器端保存到客户端
* 下载方式:
1.超链接直接指向目标资源下载:
* 如果浏览器可以解析目标文件,则直接在浏览器中打开。反之,则弹出下载提示框
2.通过Servlet实现下载
1.超链接指向servlet,传递目标资源的标识符。
2.定义Servlet
2.1获取文件标识,找到文件对象
2.2创建输入流,关联目标文件
2.3设置响应头:
content-disposition:消息体数据的打开方式
* content-disposition:attachment;filename=xxx
content-type:类型
2.4将输入流数据写入response输出流中
@WebServlet(name = "DownloadServlet",value = "/download")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.setCharacterEncoding("utf-8");
String fileName = request.getParameter("fileName");
String realPath = this.getServletContext().getRealPath("/img/" + fileName);
String agent = request.getHeader("user-agent");
if (agent.contains("MSIE")) {
fileName = URLEncoder.encode(fileName, "utf-8");
fileName = fileName.replace("+", " ");
} else if (agent.contains("Firefox")) {
BASE64Encoder base64Encoder = new BASE64Encoder();
fileName = "=?utf-8?B?"
+ base64Encoder.encode(fileName.getBytes("utf-8")) + "?=";
} else if (agent.contains("Chrome")) {
fileName = URLEncoder.encode(fileName, "utf-8");
} else {
fileName = URLEncoder.encode(fileName, "utf-8");
}
FileInputStream inputStream = new FileInputStream(realPath);
response.setHeader("content-disposition","attachment;filename="+fileName);
response.setHeader("content-type",this.getServletContext().getMimeType(fileName));
ServletOutputStream outputStream = response.getOutputStream();
IOUtils.copy(inputStream,outputStream);
}
}
注解
简介
注解(Annotation),也叫元数据。一种代码级别的说明。
它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。
它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
格式:
@interface 注解名{}
作用:
编译检查
替代配置文件
定义注解(元注解:注解上的注解)
注解属性支持的类型如下:
基本类型(四类八种)
String
Class
Annotation
Enum:枚举
以上类型对应的一维数组
注意:
1.一旦注解有属性了,使用注解的时候必须赋值,(除非这个注解属性有默认值)
2.注解中有多个属性,在给属性赋值时,用逗号隔开
3.赋值的格式:
@注解名(属性名=属性值)
我们可以通过default 关健字给属性赋上默认值
若注解类型为数组,且只有一个值的时候,可以有两种写法
方式1:
属性名 = { 值 }
方式2:
属性名=属性值
注意特殊情况若属性名为value的时候,且只需要为这个value属性赋值的时候,value可以省略
java3个常见的注解
@Override:声明该方法是从分类上继承过来的,执行编译期的检查
@SuppressWarnings:抑制警告 值有好多,只需要知道一个 all 抑制所有的警告
@Deprecated:声明 该方法不赞成使用
自定义注解
自定义注解(理解)
注解属性:
注解本质就是一个接口, 可以用javap 这个命令反编译一下 注解的字节码文件 例如 javap myan.class
接口中可以有常量和抽象方法
抽象方法在注解中就称之为注解属性
例如: public @interface MyAnnotation {
public abstract String name();
int hehe();
}
元注解
定义在自定义注解上的注解
@Retention 规定注解保留到什么阶段 值为RetentionPolicy的三个枚举值
SOURCE:只在代码中保留,在字节码文件中就删除了,不会留在Class文件中。
CLASS:在代码和字节码文件中保留,但是在运行的时候,JVM不会读取。
RUNTIME:所有阶段都保留,所以它能够通过反射调用,所以正常运行时注解都是使用
这个参数。
@Target 规定注解作用在什么上面 值为ElementType的枚举值
TYPE:作用在类 接口 等上面
METHOD:作用方法上面
FIELD:作用字段上面
案例:通过注解配置数据库连接
public class JDBCUtils {
@JdbcAnn(className = "com.mysql.cj.jdbc.Driver",url = "jdbc:mysql:///homework?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8&useSSL=false",password = "123456")
public static Connection getConnection() throws ClassNotFoundException, NoSuchMethodException, SQLException {
Connection conn=null;
Class<JDBCUtils> jdbcUtils = JDBCUtils.class;
Method getConnection = jdbcUtils.getDeclaredMethod("getConnection");
boolean f = getConnection.isAnnotationPresent(JdbcAnn.class);
if (f){
JdbcAnn annotation = getConnection.getAnnotation(JdbcAnn.class);
String name = annotation.className();
String url = annotation.url();
String username = annotation.username();
String password = annotation.password();
Class.forName(name);
conn= DriverManager.getConnection(url,username,password);
}
return conn;
}
}