文件的上传和下载 注解

文件的上传和下载

文件的上传

* 文件上传:将客户端的文件 保存到服务器端
		* 对表单限制:
			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()){
                    //获取表单项的name属性名
                    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();
                    //如果两次上传文件的文件名相同,内容会覆盖,所以拼接一个随机的uuid在文件名后面
                    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")) {
            // IE浏览器
            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")) {
            // google浏览器
            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及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。
    //注解的作用:1.起检测的作用 2.为了替代配置文件,用来简化配置
    //注解本质就是一个接口
它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
	格式:
		@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(); //注解的属性,前面的public abstract 可以省略
    				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");
        //先判断一下这个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;
    }
}                        
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值