程序员在做web等项目的时候,往往都需要添加文件上传、下载、删除的功能,有时是单文件,有时多文件批量 操作,而这些功能的代码程序员可以自己收藏起来当成工具使用,这样,程序员在进行程序设计的时候就会事半功倍 了,那么接下来的博客将会介绍各个框架的文件上传和下载功能的使用方法。 

  这篇博文主要是讲如何将多个文件压缩并下载下来:


 主要有以下几个步骤:

1。 首先先遍历出某个文件夹所含有的所有文件

import java.io.File;
import java.util.Vector;
public class A {
 public static void recursion(String root, Vector<String> vecFile) {
/*根据路径生成一个文件*/
  File file = new File(root);
  File[] subFile = file.listFiles();
/*遍历文件里面的所有文件*/
  for (int i = 0; i < subFile.length; i++) {
/*如果是文件夹,则递归下去寻找文件夹里面的文件*/
if (subFile[i].isDirectory()) { recursion(subFile[i].getAbsolutePath(), vecFile); } else {
/*如果不是文件夹的话就直接添加到vector容器里面去
(vector类称作向量类,它实现了动态数组,用于元素数量变化的对象数组。像数组一样,vector类也用从0开始的下标表示元素的位置;但和数组不同的是,当vector对象创建后,数组的元素个数会随着vector对象元素个数的增大和缩小而自动变化。)*/
2.将遍历出来的文件进行压缩和下载:

String filename = subFile[i].getName();
    vecFile.add(filename);
   }
  }
 }
 public static void main(String[] args) {
  Vector<String> vecFile = new Vector<String>();
  recursion("D:/logs/2", vecFile);
  
  for (String fileName : vecFile) {
   System.out.println(fileName);
  }
 }
}

2。 将遍历出来的文件进行压缩和下载:(一个一个压缩)

2.1 设置下载文件的名称

String fileName = "temp1.zip";
		response.setContentType("text/html; charset=UTF-8"); // 设置编码字符
		response.setContentType("application/x-msdownload"); // 设置内容类型为下载类型
		response.setHeader("Content-disposition", "attachment;filename=" + fileName);// 设置下载的文件名称
		OutputStream out = response.getOutputStream(); // 创建页面返回方式为输出流,会自动弹出下载框
		System.out.println("配置成功");



2.2 创建压缩文件需要的空的zip包

String zipBasePath = request.getSession().getServletContext().getRealPath("/logs/2/");

		/* 输出basePath的路径,方便调试 */
		System.out.println(zipBasePath);
		/* 创建压缩文件需要的空的zip包 ,这里是自动生成的,不用我们自己去生成 */
		String zipFilePath = zipBasePath + "temp.zip";
		System.out.println("create the empty zip file successfully??????");



2.3 根据临时的zip压缩包路径,创建zip文件

File zip = new File(zipFilePath);
		if (!zip.exists()) {
			zip.createNewFile();
		}
System.out.println("create the  zip file successfully");



2.4 创建zip文件输出流

FileOutputStream fos = new FileOutputStream(zip);
		ZipOutputStream zos = new ZipOutputStream(fos);
		System.out.println("create the empty zip stream successfully");



2.5 循环读取文件路径集合,获取每一个文件的路径(将文件一个一个进行压缩)

for (String fp : vecFile) {
			File f = new File(fp); // 根据文件路径创建文件
			zipFile(f, zos); // 将每一个文件写入zip文件包内,即进行打包
		}
		System.out.println("get the path successfully");
// fos.close();//如果这样关两次的话会报错,java.io.IOException: Stream closed
                zos.close();
		System.out.println("ok??");



2.6 将打包后的文件写到客户端,有两种方法可以实现(下面会进行介绍),这里使用缓冲流输出

InputStream fis = new BufferedInputStream(new FileInputStream(zipFilePath));
		byte[] buff = new byte[4096];
		int size = 0;
		while ((size = fis.read(buff)) != -1) {
			out.write(buff, 0, size);
		}
		System.out.println("package is packed successfully");



2.7 释放和关闭输入输出流

out.flush();//清楚缓存
		out.close();
		fis.close();



2.8 文件压缩的方法

public void zipFile(File inputFile, ZipOutputStream zipoutputStream) {
		try {
			if (inputFile.exists()) { // 判断文件是否存在
				if (inputFile.isFile()) { // 判断是否属于文件,还是文件夹

					// 创建输入流读取文件
					FileInputStream fis = new FileInputStream(inputFile);
					BufferedInputStream bis = new BufferedInputStream(fis);

					// 将文件写入zip内,即将文件进行打包
					ZipEntry ze = new ZipEntry(inputFile.getName()); // 获取文件名
					zipoutputStream.putNextEntry(ze);

					// 写入文件的方法,同上
					byte[] b = new byte[1024];
					long l = 0;
					while (l < inputFile.length()) {
						int j = bis.read(b, 0, 1024);
						l += j;
						zipoutputStream.write(b, 0, j);
					}
					// 关闭输入输出流
					bis.close();
					fis.close();
				} else { // 如果是文件夹,则使用穷举的方法获取文件,写入zip
					try {
						File[] files = inputFile.listFiles();
						for (int i = 0; i < files.length; i++) {
							zipFile(files[i], zipoutputStream);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


这个是我在团队中的一个项目开发过程。在这个过程中,我主要遇到了几个常见的问题,不过最后都一一被我解决掉了。

1. 因为我要下载压缩的文件是一个日志不断动态生成的文件,所以需要先对其复制到另外一个文件夹再进行压缩以及下载;

2. 对IO流的一些 知识不是很熟悉(学习并参考:)


文件从一个文件夹复制到另一个文件夹:

// 读写文件
    public static void copy1() throws Exception{  
        FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\1\\log.txt");(原文件路径)  
        FileOutputStream fos = new FileOutputStream("D:\\java1\\eclipse\\javadownload\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\SCNU_OAuth2\\logs\\1\\log.txt");  
        int len = 0;  
        byte[] buf = new byte[1024];  
        while ((len = fis.read(buf)) != -1) {  
            fos.write(buf, 0, len);  
        }  
        fos.close();  
        fis.close();  
    }
/*复制过去之后格式发生了变化,故放弃这个方法*/
	public void copy2() {
		FileWriter fw = null;
		BufferedReader br = null;
		try {
			fw = new FileWriter(
					"D:\\java1\\eclipse\\javadownload\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp1\\wtpwebapps\\SCNU_OAuth2\\logs\\1\\log.txt",
					true);
			br = new BufferedReader(new InputStreamReader(
					new FileInputStream("C:\\Users\\Administrator\\Desktop\\1\\log.txt"), "UTF-8"));(原文件路径)
			String line = null;
			while ((line = br.readLine()) != null) {
				// System.out.println("文件内容: " + line);
				fw.write(line);
				fw.flush();
			}
			br.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fw != null) {
				try {
					fw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}