IO实战-文件下载

文件下载主要分单个下载和批量下载

其实都是常规的IO操作,整体思路大概是用输入流将文件写入到指定位置,再用输出流将文件读到浏览器

1.先来介绍单个文件下载

/**
     * 单个下载
     * @param response
     * @param attachUrl 文件地址
     * @param attachName 文件名称
     * @throws IOException
     */
    public void downloadRecord(HttpServletResponse response, String attachUrl,
                               String attachName) throws IOException {
        OutputStream out=null;
        try {
            response.setContentType("audio/mp3 ");
            //注意:这里new String()的意义是为了解决中文不展示问题
            response.addHeader("Content-Disposition", "attachment;filename=" +
                    new String(attachName.getBytes("utf-8"), "ISO-8859-1"));
            out = response.getOutputStream();
            FileInputStream in= new FileInputStream (attachUrl);
            byte[] bytes = new byte[1024];
            int len = 0;
            while(-1 != (len=in.read(bytes))){
                out.write(bytes,0, len);//输出给浏览器
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(null != out){
                out.close();
            }
        }
    }

说几个细节:

1.文件名是中文的话需要用new String(attachName.getBytes("utf-8"), "ISO-8859-1")来转换以下,不然不显示

2.read(byte[])和read(byte[],int off,int len)的区别

2.再来说一说批量下载

批量下载会用到压缩包(Zip),我这边有2种思路:

①文件源地址,将需要下载的文件放到虚拟的File文件中,为什么说虚拟,因为new File(文件源url),实际上不会创建文件夹,new的File就相当于一个篮子,存放要下载的文件,然后压缩这个file,返回给浏览器。

②提供一个临时文件夹,替代如上说的“篮子”,将待下载的文件输出到临时文件夹中,压缩、返回给浏览器,最后删除掉这个临时文件夹。

//工具类 filePath:待压缩路径 zipOut:压缩流
public static void fileToZip(String fileName,String filePath,ZipOutputStream zipOut) throws IOException {
    // 需要压缩的文件
    File file = new File(filePath);
    // 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName
    //String fileName = file.getName();
    FileInputStream fileInput = new FileInputStream(filePath);
    // 缓冲
    byte[] bufferArea = new byte[1024 * 10];
    BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);
    // 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称
    zipOut.putNextEntry(new ZipEntry(fileName));
    int length = 0;
    // 最常规IO操作,不必紧张
    while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
        zipOut.write(bufferArea, 0, length);
    }
    //关闭流
    fileInput.close();
    // 需要注意的是缓冲流必须要关闭流,否则输出无效
    bufferStream.close();
    // 压缩流不必关闭,使用完后再关
}

我的应用场景是:前端传过来多条数据,后台对数据做处理

public void downloadMore(HttpServletResponse response, String rowData) throws IOException {
        String rowDataNew = StringEscapeUtils.unescapeHtml(rowData);
        List<PhoneAttachDownLoadModel>   
        phoneAttachDownLoadModels=JSONArray.parseArray(rowDataNew,
            PhoneAttachDownLoadModel.class);
        String filePath = "";
        String fileName = "";
        String zipName = "录音下载";
        //1.rowData,获取到录音地址、录音名称、指定下载到哪
        ServletOutputStream outputStream = null;
        FileInputStream inputStream = null;
        zipFilePath = FileUtils.getTempPath()+File.separator+zipName ;
        ZipOutputStream zipOutputStream=new ZipOutputStream(new FileOutputStream(zipFilePath));
        try {
            for (PhoneAttachDownLoadModel row : phoneAttachDownLoadModels) {
                filePath =row.getAttachName();//录音地址
                fileName = row.getCustomerName() +".mp3";//录音名称
                //3.调用fileToZip方法将暂存文件夹下的文件压缩成zip
                FileUtils.fileToZip(fileName,filePath,zipOutputStream);
            }
          
            //4.将zip输出给浏览器
            response.setHeader("Content-Disposition", "attchment;filename=" +
                    new String(zipName.getBytes("utf-8"), "ISO-8859-1")+".zip");
            outputStream = response.getOutputStream(); //向页面发送流数据
            inputStream = new FileInputStream(tempFloder+File.separator+zipName+".zip");
            IOUtils.copy(inputStream, outputStream);
        } catch (IOException e) {
            log.info("批量下载失败");
            e.printStackTrace();
        }finally {
            // 关闭输入流
            if (inputStream != null){
                inputStream.close();
            }
            if (outputStream != null){
                outputStream.close();
            }
            if (zipOutputStream!= null){
                zipOutputStream.close();
            }
        }
        //5.删除暂存文件夹中的文件
        File file=new File(tempFloder);
        FileUtils.deleteFile(file);
    }

细节说明:

1.用StringEscapeUtils.unescapeHtml(rowData)来处理&quot;

2.先使用的流后关闭

3.ServletOutputStream流不需要关闭,并且可以通过response.getOutputStream()获取


一个录音下载,我写了有10次,都没有搞得很明白,如果大家有不明白的地方,我们一起讨论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值