Java文件上传下载

Java文件上传下载

在上传图片之前,预览图片,可参考Preview an image before it is uploaded

基本原理

文件上传原理

通过为表单元素设置Method="post" enctype="multipart/form-data"属性,让表单提交的数据以二进制编码的方式提交,在接收此请求的Servlet中用二进制流来获取内容,就可以取得上传的文件的内容,从而实现文件的上传。
enctype

通过例子来说明,我们上传一个demo.txt文件,其内容仅为Hello。在Window上通过Fiddler,在Mac上通过Charles(Chrome中貌似不显示上传的内容),来获取请求提交内容,可能如下:

POST /Java_upload/uploadServlet.do HTTP/1.1
Host: localhost:8080
Content-Length: 189
Cache-Control: max-age=0
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryv4NMXWJ1jyLQItjJ
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost:8080/Java_upload/jsp/01.jsp
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: JSESSIONID=826E060D479FB980BEBFDAEDA60C0842; _ga=GA1.1.746910066.1493867756; _gid=GA1.1.1530689773.1506644790

------WebKitFormBoundaryv4NMXWJ1jyLQItjJ
Content-Disposition: form-data; name="myfile"; filename="demo.txt"
Content-Type: text/plain

Hello
------WebKitFormBoundaryv4NMXWJ1jyLQItjJ--

如果上传一个图片,其效果如下:

这里写图片描述

所以在后台就可以通过流读取上传文件的内容

文件下载原理

文件下载原理

JSP+Servlet实现文件上传下载

上传

上传思路实现

    <form action="<%=path %>/uploadServlet.do" method="post" enctype="multipart/form-data">
        请选择图片:<input id="myfile" name="myfile" type="file" >
        <input type="submit" value="提交" />
    </form>

文件上传

1.获取request中的流信息,保存到临时文件
如下,保存到tempFile.txt文件中

        InputStream is = request.getInputStream();//获取当前流信息
        //临时文件
        String tempFileName = "/Users/Miller/Pictures/upload/tempFile.txt";
        File tempFile = new File(tempFileName);
        FileOutputStream fos = new FileOutputStream(tempFile);
        //写入临时文件
        byte[] b = new byte[1024];
        int n;
        while ((n = is.read(b)) != -1) {
            fos.write(b, 0, n);
        }
        //关闭输入流,输出流
        fos.close();
        is.close();

以上传上面的demo.txt文件为例,此时tempFile.txt文件内容为:

------WebKitFormBoundaryBpKti4hleQGq6sUJ
Content-Disposition: form-data; name="myfile"; filename="demo.txt"
Content-Type: text/plain

Hello
------WebKitFormBoundaryBpKti4hleQGq6sUJ--

2.获取文件内容起止位置
a.获取上传的文件名(Mac示例)

        //获取文件名称
        RandomAccessFile randomFile = new RandomAccessFile(tempFile, "r");
        //读取第二行内容
        randomFile.readLine();
        String str = randomFile.readLine();
        int beginIndex = str.lastIndexOf("=")+2;
        int endIndex = str.lastIndexOf("\"");//最后一个引号的位置
        String filename = str.substring(beginIndex, endIndex);
        System.out.println("filename = " + filename);

上传完整代码

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("已接收到请求");
        //从request当中获取流信息
        InputStream fileSource = req.getInputStream();
        String tempFileName = "E:/tempFile";
        //tempFile指向临时文件
        File tempFile = new File(tempFileName);
        //outputSteam文件输出流指向这个临时文件
        FileOutputStream outputStream = new FileOutputStream(tempFile);
        byte b[] = new byte[1024];
        int n;
        while((n = fileSource.read(b)) != -1){
            outputStream.write(b, 0, n);
        }
        //关闭输出流、输入流
        outputStream.close();
        fileSource.close();

        //获取上传的文件的名称
        RandomAccessFile randomFile = new RandomAccessFile(tempFile, "r");
        randomFile.readLine();
        String str = randomFile.readLine();
        int beginIndex = str.lastIndexOf("\\")+1;
        int endIndex = str.lastIndexOf("\"");
        String filename = str.substring(beginIndex, endIndex);

        //重新定位文件指针到文件头
        randomFile.seek(0);
        long startPostion = 0;
        int i = 1;
        //获取文件内容的开始位置
        while((n = randomFile.readByte()) != -1 && i <= 4){
            if(n == '\n'){
                startPostion = randomFile.getFilePointer();
                i++;
            }
        }
        //startPostion = startPostion - 1;
        //获取文件内容的结束位置
        randomFile.seek(randomFile.length());
        long endPosition = randomFile.getFilePointer();
        int j = 1;
        while(endPosition >= 0 && j<=2){
            endPosition--;
            randomFile.seek(endPosition);
            if(randomFile.readByte() == '\n'){
                j++;
            }
        }
        endPosition = endPosition - 1;

        //设置保存文件上传文件的路径
        String realPath = getServletContext().getRealPath("/")+"images";
        File fileupload = new File(realPath);
        if(!fileupload.exists()){
            fileupload.mkdir();
        }
        File saveFile = new File(realPath, filename);
        RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile, "rw");
        //从临时文件中读取文件内容(根据起止位置获取)
        randomFile.seek(startPostion);
        while(startPostion < endPosition){
            randomAccessFile.write(randomFile.readByte());
            startPostion = randomFile.getFilePointer();
        }
        //关闭输入输出流、删除临时文件
        randomAccessFile.close();
        randomFile.close();
        tempFile.delete();

        req.setAttribute("result", "上传成功!");
        RequestDispatcher dispatcher = req.getRequestDispatcher("jsp/01.jsp");
        dispatcher.forward(req, resp);
    }

下载

下载实现思路
下载实现思路

<a href="<%=path %>/downloadServlet.do?filename=00.jpg">text.txt</a>
package com.imooc.servlet;

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

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

public class DownloadServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取文件下载路径
        String path = getServletContext().getRealPath("/")+"images/";
        String filename = req.getParameter("filename");
        File file = new File(path+filename);
        if (file.exists()) {
            //设置相应类型或者application/octet-stream
            resp.setContentType("application/x-msdownload");
            //设置头信息
            resp.setHeader("Content-Disposition", "attachment;filename=\""+filename+"\"");
            InputStream inputStream = new FileInputStream(file);
            ServletOutputStream outputStream = resp.getOutputStream();
            byte b[] = new byte[1024];
            int n;
            while((n = inputStream.read(b)) != -1){
                outputStream.write(b, 0, n);
            }
            //关闭流、释放资源
            outputStream.close();
            inputStream.close();

        }else{
            req.setAttribute("errorResult", "文件不存在,下载失败!");

        }
    }

}

SmartUpload

上传
如下上传文件:

    <form action="smartupload_demo01.jsp" method="post" enctype="multipart/form-data">
        选择文件1:<input type="file" name="myfile1"><br/>
        选择文件2:<input type="file" name="myfile2"><br/>
        选择文件3:<input type="file" name="myfile3"><br/>
        <input type="submit" value="上传">
    </form>

处理过程如下:

        //设置上传文件保存路径
        String filePath = getServletContext().getRealPath("/")+"images";
        File file = new File(filePath);
        if(!file.exists()){
            file.mkdir();
        }

        SmartUpload su = new SmartUpload();
        //初始化对象
        su.initialize(getServletConfig(), request, response);
        //设置上传文件大小
        su.setMaxFileSize(1024*1024*10);
        //设置所有文件大小
        su.setTotalMaxFileSize(1024*1024*100);
        //设置允许用户上传文件类型
        su.setAllowedFilesList("txt,jpg,png,gif");
        String result    = "上传成功";
        //设置禁止上传文件类型
        try{
            su.setDeniedFilesList("rar,jsp,js");
            //上传文件
            su.upload();
            int count = su.save(filePath);


        }catch(Exception e){
            e.printStackTrace();
            result = "上传失败";
        }

异常处理

            if(e.getMessage().indexOf("1015") != -1){
                result = "上传失败:上传文件类型不正确!";
            }else if(e.getMessage().indexOf("1010") != -1){
                result = "上传失败:上传文件类型不正确!";
            }else if(e.getMessage().indexOf("1105") != -1){
                result = "上传失败:上传文件大小大于允许的最大值!";
            }else if(e.getMessage().indexOf("1110") != -1){
                result = "上传失败:上传文件总大小大于允许的最大值!";
            }

通过SmartUpload获取上传文件的其他属性

        for(int i = 0; i < su.getFiles().getCount(); i++){
            org.lxh.smart.File tempFile = su.getFiles().getFile(i);
            System.out.println("--------");
            System.out.println("表单当中name的值:"+tempFile.getFieldName());
            System.out.println("上传文件名:"+tempFile.getFileName());
            System.out.println("上传文件的大小:"+tempFile.getSize());
            System.out.println("上传文件的拓展名:"+tempFile.getFileExt());
            System.out.println("上传文件的全名:"+tempFile.getFilePathName());
            System.out.println("--------");
        }

输出结果如下:

表单当中name的值:myfile3
上传文件名:2.png
上传文件的大小:316681
上传文件的拓展名:png
上传文件的全名:2.png

下载

下载:<a href="smartDownloadServlet.do?filename=img2-lg.jpg">img2-lg.jpg</a>

SmartDownloadServlet如下:

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String filename = req.getParameter("filename");
        SmartUpload su = new SmartUpload();
        su.initialize(getServletConfig(), req, resp);
        su.setContentDisposition(null);
        try {
            su.downloadFile("/images/"+filename);
        } catch (SmartUploadException e) {
            e.printStackTrace();
        }

    }

使用SmartUpload实现文件批量下载
如何实现文件的批量下载?

    <form action="smartDownloadServlet.do">
        <input type="checkbox"  name="filename" value="img2-lg.jpg">Image2
        <input type="checkbox"  name="filename" value="img3-lg.jpg">Image3
        <input type="checkbox"  name="filename" value="img4-lg.jpg">Image4
        <input type="submit" value="下载">
    </form>

servlet处理

        resp.setContentType("application/x-msdownload");
        resp.setHeader("Content-Disposition", "attachment;filename=test.zip");

        String filepath = getServletContext().getRealPath("/")+"images/";
        String[] filenames = req.getParameterValues("filename");
        String str = "";
        String rt = "\r\n";
        ZipOutputStream zipOutputStream  = new ZipOutputStream(resp.getOutputStream());
        for(String filename : filenames){
            str += filename+rt;
            File file = new File(filepath+filename);
            zipOutputStream.putNextEntry(new ZipEntry(filename));
            FileInputStream fis = new FileInputStream(file);
            byte b[] = new byte[1024];
            int n = 0;
            while((n = fis.read(b)) != -1){
                zipOutputStream.write(b, 0, n);
            }
            zipOutputStream.flush();
            fis.close();
        }
        zipOutputStream.setComment("download success:"+rt+str);
        zipOutputStream.flush();
        zipOutputStream.close();
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值