码迷,mamicode.com
首页 > 编程语言 > 详细

javaweb-文件的上传下载

时间:2016-05-15 21:19:42      阅读:441      评论:0      收藏:0      [点我收藏+]

标签:

本文用到的jar:

文件上传:commons-fileupload-1.2.1.jar;

 commons-io-1.4.jar;

本文需要掌握的知识:html+dom

1 文件的上传概述;

1.1 用户把本地的文件储存到服务器上,就是文件的上传;

1.2 实现文件的上传(目前而言要使用第三方jar);

  1.2.1 jspSmartupload;

适用范围:应用在jsp的模型一里(嵌入执行上传下载操作的JSP文件中)  ;

  1.2.2 fileUpload;

     来源:Apache commons下面的开源,免费项目(谢谢老板);

 适用范围:(mvc模式);

1.3 要使用文件的上传,需要满足三个要求:

  ①表单数据提交,提交方式为post提交;

  ②在表单里有一个文件的上传想<input type=”file” name=”filename”/>

  ③在form里面,要设置一个属性值,enctype,设置为multipart/form-data(必须设置,不然只有一个文件名之类的)

 

2  文件上传的原理分析:

从请求响应信息可知;

Content-Type:multipart/form-data;

通过请求正文可以得到结论:

①找到分割线;

②根据分割线区别不同的项;

③普通输入项得到的是值;

④文件上传项,得到文件的内容,把内容写到服务器里面一个文件中;

⑤使用输入流得到文件上传的内容,使用输出流把文件的内容写到服务器上;

 

3,文件上传的代码实现的步骤(固定步骤,照着写就可以了);

  3.1 :创建磁盘文件工厂;

new DiskFileItemFactory();

  3.2:创建核心上传类;

new ServletFileUpload(FileItemFactory fileItemFactory);

  3.3:使用核心上传类解析request对象;

parseRequest(-----request(全类名就不写了));

返回的是一个List集合,集合中有多个FileItem,泛型为<FileItem>;

  3.4:遍历list集合,得到每个FileItem;

  3.5:判断是普通输入项还是文件上传项;

      Boolean isFormField();

  3.6:如果是普通输入项;如果是文件上传项编写文件上传的代码;

普通输入项:

getField():得到普通输入项name的值;

getString():得到普通输入项里面输入的值;

文件上传项:

得到通过表单提交的文件的输入流,getInputStream;

创建输出流,写出文件到服务器的相应的位置(输出位置要带有盘符,通过

getServletContext().getRealPath(相对路径)可以获取.为什么要这样做,是因为项目在别的服务器上真实路径就不一定一致了,所以要通过相对路径获取到真实路径);

 

4,核心API的学习(主要是一些重要的方法);

4.1 DiskFileItemFactory(磁盘文件项工厂)(核心上传类,重点在于构造);

构造方法;

DiskFileItemFactory(int sizeThreshold,java.io.File repository);

两个参数:

第一个参数设置上传文件缓冲区的大小;

第二个参数.如果上传文件超出了缓冲区,产生临时文件,设置临时文件路径

(可以看做是先用一个等大小的临时文件做占位,然后数据一步步填充);

DiskFileItemFactory() 无参构造,也可以设置缓冲区;

setSizeThreadshold(int sizeThreadshold):设置上传文件的缓冲区(单位是字节byte);

setRepository(java.io.File repository):设置临时文件路径;

 

 

4.2 ServletFileUpload:核心上传类;

   构造方法;

   ServletFileUpload(FileItemFactory fileItemFactory);

重要方法:;

parseRequest(javax.servlet.HttpServletRequest request):解析request对象;

返回一个list<FileItem>集合,每一个元素都是一个FileItem;

在他的父类中还有一个很重要的方法;

setHeaderEncoding(java.lang.String encoding);设置上传文件名称的编码;

 

setFileSizeMax(long filesizeMax)”:设置单个文件的大小;

 

setSIzeMax(long sizeMax): 设置单个文件的总大小;

 

4.3 FileItem:文件项

    Boolea isFormField():判断是否是普通输入项;

getFieldName():得到普通输入项.name的属性值;

getString():得到普通输入项的文本值;

getString(encoding):设置输入项中文本的编码;

getName():得到上传文件的名称(但是有些浏览器得到的带路径的名称,所以要进行截取操作,);

getInputStream():得到表单提交的文件输入流;

Delete():删除临时文件(要在关闭流之后删除);

 

5 JS控制多文件的上传

5.1 需求:在上传的表单里面有两个按钮,一个是上传文件的按钮,一个是增加的按钮,增加上传项.

点击增加按钮之后,增加一行,一个上传输入项和一个删除的按钮

点击删除按钮之后,删除该行

点击上传按钮之后,把当前的文件上传到服务器里面去

 5.2 使用js增加一行和删除一行

<script type="text/javascript">

//增加一行

function addFile(){

//table里面增加一行

var table = document.getElementsByTagName("table")[0];

table.innerHTML+="<tr><td><input type=‘file‘ name=‘filename‘/></td><td><input type=‘button‘ value=‘删除‘ onclick=‘dele(this)‘/><td/><tr/> ";

}

//删除一行

function dele(who){

//获取当前点击的删除按钮所在的tr

var tr=who.parentNode.parentNode;

//拿到爸爸

var table=tr.parentNode;

//通过爸爸删除儿子

table.removeChild(tr);

}

</script>

 

5.3 使用button提交表单的方法

//通过按钮提交表单实现上传

function uploadFile(){

var form =document.getElementsByTagName("form")[0];

form.submit();

}

 

5.4 常见问题的解决:

5.4.1 当已经存在名字重复的文件,再次上传会新文件覆盖原文件

解决方式:在上传的文件名称里添加一个随机的唯一的字符串,保证每个文件都是唯一的值(可以通过uuid生成,也可以使用毫秒数,不过推荐用uuid更加保险

//生成一个随机的唯一的id

String id = UUID.randomUUID().toString();

 JSP页面(为什么我没找到jsp代码选择)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="${pageContext.request.contextPath }/servlet/Upload2" method="post"  enctype="multipart/form-data">
        <input type="button" value="上传" onclick="uploadFile()"/>
        <input type="button" value="增加" onclick="addFile()"/><hr/>
        <table>
            
        </table>
        <%--
        <input type="file" name="filename"/><input type="button" value="删除"/> 
        --%></form>
</body>
<script type="text/javascript">
    //通过按钮提交表单实现上传
    function uploadFile(){
        var form =document.getElementsByTagName("form")[0];
        form.submit();
    }
    //增加一行
    function addFile(){
        //在table里面增加一行
        var table = document.getElementsByTagName("table")[0];
        table.innerHTML+="<tr><td><input type=‘file‘ name=‘filename‘/></td><td><input type=‘button‘ value=‘删除‘ onclick=‘dele(this)‘/><td/><tr/> ";
    }
    //删除一行
    function dele(who){
        //获取当前点击的删除按钮所在的tr
        var tr=who.parentNode.parentNode;
        //拿到爸爸
        var table=tr.parentNode;
        //通过爸爸删除儿子
        table.removeChild(tr);
    }
</script>
</html>

servlet处理页面(对应的图片文件就不放上来了)

package com.zzx.upload;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class Upload2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            //1,創建磁盤文件工廠
            DiskFileItemFactory dff = new DiskFileItemFactory();
            //2,創建核心上傳類
            ServletFileUpload fileupload = new ServletFileUpload(dff);
            fileupload.setHeaderEncoding("utf-8");
            //3,解析对应的请求数据
            List<FileItem> fl = fileupload.parseRequest(request);
            for (FileItem fileItem : fl) {
                 //判断是否是普通输入项
                if(fileItem.isFormField()){
                    //如果是普通输入项,就得到普通输入项name的属性值,和输入的值
                    String name = fileItem.getFieldName();
                    String value = fileItem.getString();
                    System.out.println(name + ":" + value);
                }else{
                    //如果是文件上传项
                    //获取上传的文件名称,但是有的浏览器里面带的是带路径的名称
                    String filename = fileItem.getName();
                    //优化,判断是否带/,如果带"/"就进行截取,否则就直接用
                    int lens=filename.lastIndexOf("/");
                    if(lens!=-1){
                        filename=filename.substring(lens+1);
                    }
                    //获取文件上传的输入流
                    InputStream is =fileItem.getInputStream();
                    //得到文件夹带盘符的路径
                    String path = getServletContext().getRealPath("/upload");
                    //输出流
                    OutputStream os =new FileOutputStream(path + "/" + filename);
                    //流对接
                    int len=0;
                    byte[]arr =new byte[1024*8];
                    while((len = is.read(arr))!=-1){
                        os.write(arr,0,len);
                    }
                    //关流
                    is.close();
                    os.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}

 

6 文件的下载:

6.1 把服务器上文件保存到本地硬盘,这个过程称为文件的下载

6.2 文件下载的实现方式:

  6.2.1:  实现超链接的文件下载

弊端:有的文件无法实现下载,而是显示在页面上(比如图片)

      6.2.2:  通过代码实现文件下载

无论什么格式的文件都可以下载

实现步骤:

0:设置要下载的文件MIME类型(可选)

第一步:设置头信息,Content-Disposition,无论什么格式,都是以下载的方法打开

第二步:服务器得到文件的输入流

第三步:创建输出流,写出到浏览器

第四步:流对接

 

具体代码:

 

6.3 常见问题:

6.3.1 当文件名携带中文的时候(中文名称会乱码,不显示之类的问题)

        6.3.2 原因:不同浏览器编码不同

        ie浏览器采用的是url编码,

        火狐浏览器采用的是base64编码,

   6.3. 3  ① 区分不同的浏览器

 通过请求头 User-Agent,得到当前浏览器的请求类型

  ②根据不同的浏览器设置不同的编码(IE,谷歌解决方式一致)

这里是文件下载的页面

 

package com.zzx.down;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

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

import sun.misc.BASE64Encoder;

import com.sun.xml.internal.messaging.saaj.util.Base64;
/*
 * 这个页面是实现文件的下载
 */
public class DownServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
            //0,得到文件的路径
        String path = getServletContext().getRealPath("/down/图片.jpg");
            //得到文件名
            //这里寻找"/"要注意使用"\\"才能正确的截取
        String filename = path.substring(path.lastIndexOf("\\")+1);
        //得到请求的浏览器类型
        String agent = request.getHeader("User-Agent");
        //判断浏览器类型
        System.out.println(agent);
        if(agent.contains("Firefox")){
            //如果是火狐,进行base64编码
            filename = "=?UTF-8?B?"+new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";
        }else{
            //url编码,谷歌,IE都可以通过这样设置
            filename=URLEncoder.encode(filename, "UTF-8");
        }
            //1,设置文件的mime类型
            //先得到文件的mime类型
        String type = getServletContext().getMimeType(filename);
            //设置
        response.setContentType(type);
        response.setHeader("Content-Disposition", "attachment;filename=" + filename);
           //得到输入流
        InputStream is = new FileInputStream(path);
           //得到输出流
        OutputStream os = response.getOutputStream();
           //2,流对接
        int a=0;
        byte[]arr =new byte[1024*8];
        while((a = is.read(arr))!=-1){
            os.write(arr,0,a);
        }
        //3,关流
        os.close();    //会自动关闭,不过要养成关流的习惯
        is.close();
        
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}

 

javaweb-文件的上传下载

标签:

原文地址:http://www.cnblogs.com/adventurer/p/5496040.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!