文件上传和下载

一.文件的上传
(一)基本概念及其入门案例
1.什么是文件上传:将本地的文件上传到服务器端。
2.应用:百度网盘,上传照片,上传附件。
3.javaweb端实现文件上传;
客户端:需要文件的输入项 <input type="file"/>
必须有三点设置:
1)type="file" name 必须有 name="myfile"
2)form表单 method="post"提交方式 (get参数显示在url上,get数据大小1k)
3)form表单 enctype="multipart/form-data" 编码格式
服务端:写一段文件上传的程序。
requestl.getInputStream(); 获取输入流
System.out.write();

4.fileupload 文件上传的组件
1)jspsmartupload 上传组件,嵌入在jsp中。model1时代,jsp。
2)jsp+servlet时代 fileuplaod

5.fileupload的jar commons-fileupload-1.2.1jar包和commons-io-1.4jar包 要一起使用。 依赖。

package cn.itcast.servlet;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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 cn.itcast.util.UploadUtil;

public class UploadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String filedesc = request.getParameter("filedesc");
        System.out.println("文件描述:"+filedesc);
        // 获取输入流
        //InputStream in = request.getInputStream();
        // 打印控制台上
        /*int b;
        while((b = in.read()) != -1){
            System.out.write(b);
        }
        System.out.flush();*/
        
        if(!ServletFileUpload.isMultipartContent(request)){
            throw new RuntimeException("请设置正确的enctype");
        }
        
        /**
         * 1.创建磁盘文件项工厂
         */
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置内存缓冲区的大小
        factory.setSizeThreshold(2*1024*1024);  //2M
        // 设置临时文件的存储位置
        String temppath = this.getServletContext().getRealPath("/temp");
        File filetemp = new File(temppath);
        factory.setRepository(filetemp);
        
        /**
         * 2.创建文件上传类
         */
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 设置上传文件的总大小
        upload.setSizeMax(50L*1024*1024); // 50M
        // 设置文件名称的编码
        upload.setHeaderEncoding("UTF-8");
        
        /**
         * 3.解析request
         */
        try {
            List<FileItem> list = upload.parseRequest(request);
            /**
             * 4.循环遍历list集合,拿到fileItem对象,判断是否普表单项
             */
            for (FileItem fileItem : list) {
                // isFormField()
                if(fileItem.isFormField()){
                    // 普通表单项
                    // 获取参数的名称
                    String name = fileItem.getFieldName();
                    // 获取值
                    //String value = fileItem.getString();
                    String value = fileItem.getString("UTF-8");
                    System.out.println(name+" = "+value);
                }else{
                    // 文件上传项
                    // 获取文件的名称
                    String filename = fileItem.getName();
                    // 先判断filename不能空
                    if(filename == null || filename.trim().length() == 0){
                        throw new RuntimeException("请选择文件");
                    }
                    // 解决IE6的问题  D:\class\resource\hello.txt
                    int index = filename.lastIndexOf("\\");
                    if(index != -1){
                        filename = filename.substring(index+1);
                    }
                    //解决文件名重名的问题
                    filename = UUID.randomUUID().toString()+"_"+filename;
                    // 目录分离
                    String dir = UploadUtil.getRanromDir(filename);
                    
                    System.out.println("文件名称:"+filename);
                    // 获取输入流
                    InputStream in = new BufferedInputStream(fileItem.getInputStream());
                    // 先获取upload的绝对路径
                    String filepath = this.getServletContext().getRealPath("/upload"+dir);
                    // 创建多级目录
                    new File(filepath).mkdirs();
                    // 创建file对象
                    File file = new File(filepath,filename);
                    // 输出流
                    OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
                    int b;
                    while((b = in.read()) != -1){
                        os.write(b);
                    }
                    os.close();
                    in.close();
                    // 删除临时文件(必须写在流关闭之后)
                    fileItem.delete();
                }
            }
            
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        System.out.println(System.getProperty("java.io.tmpdir"));
    }

}

 


(二)入门案例存在的问题
1.IE6上传文件的问题:
产生原因:把文件的绝对路径传过来了。
解决办法:切割。把文件名称切出来。
// 解决IE6的问题 D:\class\resource\hello.txt
int index = filename.lastIndexOf("\\");
if(index != -1){
filename = filename.substring(index+1);
}
2.注意事项(*****)
String filedesc = request.getParameter("filedesc"); 在文件上传 enctype="multipart/form-data"拿不到值了。
想拿到值就下面方法。
// 获取参数的名称
String name = fileItem.getFieldName();
// 获取值
String value = fileItem.getString();

(三)文件上传的核心类及其API
1.磁盘文件项工厂类 DiskFileItemFactory
1)DiskFileItemFactory(int sizeThreshold, java.io.File repository) 第一个参数内存缓冲区的大小 第二个参数临时文件的存储位置
内存缓冲区:上传文件时,文件首先会上传到内存缓冲区中,上传的文件的大小超过设置的内存缓冲区的大小,就会产生临时文件。
临时存储位置:用来保存临时文件的。

2)void setSizeThreshold(int sizeThreshold) 设置内存缓冲区的大小 默认10k
3)void setRepository(java.io.File repository) 设置临时文件存储位置 System.getProperty("java.io.tmpdir") C:\Users\ADMINI~1\AppData\Local\Temp\

2. 文件上传类 ServletFileUpload
1)static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request) 判断enctype是否是multipart方式
2)java.util.List parseRequest(javax.servlet.http.HttpServletRequest request) 解析request 返回list<FileItem>集合
3)void setSizeMax(long sizeMax) 设置上传所有文件的总大小 和 void setFileSizeMax(long fileSizeMax) 设置单个上传文件的大小
4)(*****)void setHeaderEncoding(java.lang.String encoding) 设置编码 可以解决中文文件名乱码的问题
5)void setProgressListener(ProgressListener pListener) 设置进度条的监听器 进度条速度 剩余时间 剩余大小

3. 文件项FileItem
1)boolean isFormField() 判断是否是普通表单项还是文件上传项
if(fileItem.isFormFiele()){
// 表单
2)java.lang.String getFieldName() 获取参数的名称
3)java.lang.String getString() 获取值
4)(*****)java.lang.String getString(java.lang.String encoding) 设置表单中文的编码 解决普通表单项的中文乱码的问题
}else{
// 文件
5)java.io.InputStream getInputStream() 获取输入流
6)java.lang.String getName() 获取文件名称
}
7)void delete() 删除临时文件((必须写在流关闭之后))

(四)多文件上传案例(js控制)
需求:多文件上传。

(五)上传文件的扩展
1.上传文件存放目录问题:
1)在webroot目录下,安全级别较低,允许用户直接访问。
购物商城的网站:京东。

2)上传文件目录访问WEB-INF目录下,安全级别较高。通过程序。
例子:视频网站。

2.文件名重名的问题
解决办法:UUID+"_"+文件名称

3.解决一个目录内文件过多的问题(目录分离算法)
1)根据上传文件的时间(周,月)
2)根据上传文件的数量(3000)
3)根据用户创建一个文件夹(张三,李四)
4)根据唯一文件名的hashcode值算法。


二.文件的下载
(一)基本概念及其入门案例
1.什么的文件的下载:将服务器的文件下载到本地。
2.应用:百度网盘,下载歌曲,下载图片。
3.javaweb实现文件的下载:
1)超链接下载 <a href="文件的绝对路径">文件名称</a>
浏览器可以解析你文件的格式。浏览器直接打开。

2)程序的文件下载。
接收文件的名称,获取download的绝对路径,并且拼接file对象,读入到输入流中。
两点注意:两个头一个流
两个响应头:设置Content-Type 属性 MIME类型
设置Content-Disposition 值attachment;filename= + 文件名称 以附件的形式打开。
一个响应流:向浏览器输出 response.getOutputStream()

(二)文件下载扩展案例
需求:在磁盘随便指定一个目录,要把该目录下的所有文件及其子目录下的所有文件列在页面上,并且提供下载。
采用广度非递归的遍历,依赖于数据结构。队列 FIFO 先进先出 JDK5.0 提供了接口 Queue

package cn.itcast.servlet;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 下载的入门案例
 * @author Administrator
 *
 */
public class DownloadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取文件的名称
        String filename = request.getParameter("filename");
        // 获取download的绝对路径
        String filepath = this.getServletContext().getRealPath("/download");
        // 创建file对象
        File file = new File(filepath,filename);
        // 读入到输入流
        InputStream in = new BufferedInputStream(new FileInputStream(file));
        // 设置两个头
        String mimeType = this.getServletContext().getMimeType(filename);
        // 设置类型
        response.setContentType(mimeType);
        // 设置以附件形式打开
        response.setHeader("Content-Disposition", "attachment;filename="+filename);
        // 输出流
        OutputStream os = response.getOutputStream();
        int b;
        while((b = in.read()) != -1){
            os.write(b);
        }
        os.close();
        in.close();
    }

}

 


2.get方式提交 中文乱码
filepath = new String(filepath.getBytes("ISO-8859-1"),"UTF-8");

3.IE6中文乱码
产生原因:代码没有问题。IE6对中文的编码有bug。
解决办法:自己编码。URLEncoder.encode(f.getCanonicalPath(), "UTF-8")

4.弹出的下载框显示的中文乱码


三.JavaMail(邮件)
(一)邮件的基本概念及其传输过程
1.为什么学习邮件:比较好的用户体验,比较火的技术。
2.常见邮件:祝福邮件,通知邮件,垃圾邮件

3.基本概念
1)邮件服务器:是一台电脑,装关于邮件服务器的软件。收发邮件。
2)电子邮箱:邮件服务器上的账号,在邮件服务器分配一块空间,用来保存邮件。

3)邮件的传输协议:
发送邮件协议:SMTP协议 默认端口 25

接收邮件协议:POP3协议 默认端口 110

接收邮件协议:IMAP协议 默认端口 143
区别:允许不用下载,直接在服务器端可以修改。
gmail 支持IMAP

4.邮件的传输过程
看图七

(二)通过telnet命令手动发送邮件(网络)
1.如果是win7的系统,需要手动开启telnet命令。如果xp不用。
2.发送邮件的协议(SMTP)
1)telnet smtp.sina.com 25 链接新浪的发送邮件的服务器
2)ehlo hi 打个招呼
3)auth login 是否需要登陆认证
4)输入用户名 (必须要经过BASE64进行编码)
5)输入密码
6)mail from:<javamail_day@sina.com> 发件人
7)rcpt to:<javamail_day@163.com> 收件人
8)Data RFC822文档(规范)
9)输入邮件内容(RFC822文档)
10). 代表邮件的结束
11)quit 断开链接


3.RFC822文档
包含邮件头 和邮件体,中间用空行分隔。
邮件头:
from:<javamail_day@sina.com> 发件人
to:<javamail_day@163.com> 收件人
subject:girl 邮件的标题

邮件体:
I LOVE YOU TOO TOO

4.接收邮件的协议 POP3协议
telnet pop3.163.com 110 链接接收邮件服务器
user 输入用户名
pass 输入密码
stat 返回邮件的数量
list 返回邮件列表结合
retr 2 访问第二封邮件
quit 端口链接

(三)邮件服务器,客户端安装及其telnet命令发送邮件(本机)
1.安装邮件服务器
配置:工具--服务器设置--修改域名(estore.com)
新建账号:账号--新建账号。

2.安装客户端软件
安装foxmail。
配置:建立新的账户:bbb@estore.com 密码111
指定邮件服务器:localhost


(四)通过JavaMail创建简单的邮件
1.javamial sun官方提供api,关于邮件的api。
2.下载jar包 javamail1_4_4和jaf-1_1_1 包,必须一起使用,依赖。
JDK6.0之后 jaf内置。如果是JDK1.6版本之前,需要引入jaf的包。

3.入门案例。
1)Session 链接服务器会话。
2)Message 邮件对象
3)Transport 发送邮件工具类

4.邮件的内容打印在控制台上保存
java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream
产生的原因:myeclipse自带的jar与javamail的jar包冲突导致。
解决办法:

posted @ 2019-01-16 13:01  悦文  阅读(657)  评论(0编辑  收藏  举报