继上一篇博客--javaweb通过接口来实现多个文件压缩和下载(包括单文件下载,多文件批量下载)

通过动态分配地址来提升javaweb文件下载接口的其兼容性和可扩展性:

(上篇博文地址:https://blog.csdn.net/weixin_37766296/article/details/80044000)


log4j.properties 文件:

log4j.rootLogger = debug,stdout,D,E

 log4j.logger.java.sql.ResultSet=INFO
 log4j.logger.java.sql.apache=INFO
 log4j.logger.java.sql.Connnection=DEGUG
 log4j.logger.java.sql.Statement=DEGUG
 log4j.logger.java.sql.PreparedStatement=DEGUG

 log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
 log4j.appender.D.File = 
 log4j.appender.D.Append = true
 log4j.appender.D.Threshold = DEBUG 
 log4j.appender.D.layout = org.apache.log4j.PatternLayout
 log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
 
 
 log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
 log4j.appender.E.File = 
 log4j.appender.E.Append = true
 log4j.appender.E.Threshold = ERROR 
 log4j.appender.E.layout = org.apache.log4j.PatternLayout
 log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n 

你会发现:

log4j.appender.D.File =

这里是空的,不急,容我慢慢解释。

上面是日志文件的配置。下面是web.xml文件的配置:

	<!-- log4j文件的配置 (千万要注意的是下面的classes记得加上去,虽然工程目录可能没有,但是实际目录可能是有的)-->
<servlet>    
    <servlet-name>lo4jInit</servlet-name>    ()
    <servlet-class>com.fx.init.Lo4jInit</servlet-class>    (这里要慎重,servlet类名:由package+class名组成)
    <init-param>    
        <param-name>log4j_init_path</param-name>           (这里是用来初始化的一些参数,在init()方法中通过getInitParameter()方法获得)
        <param-value>WEB-INF\classes\log4j.properties</param-value>   (跟上面一个参数匹配,类似于一对键值对) 
   </init-param>      
   <load-on-startup>0</load-on-startup>    
 </servlet> 

web容器启动时是先 初始化web.xml文件,然后在根据web.xml中的配置进行部署

接下来就是init()方法的实现了。。



public class Lo4jInit extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static Logger logger = Logger.getLogger(Lo4jInit.class);

	/* web容器初始化 */
	public void init() {
		/* 部署在tomcat下的绝对路径 */
		String path = this.getServletContext().getRealPath("/");
		/* 获取web.xml文件中name为log4j_init_path的value值 */
		String file = this.getInitParameter("log4j_init_path");

		if (file != null) {
			Properties prop = new Properties();
			String root = path;
			/* 设置文件输出的路径 */
			String root1 = root + "/logs/log.txt";
			String root2 = root + "logs/error.txt";

			System.out.println("root1:" + root1);
			System.out.println("root2:" + root2);
			
			try {
				prop.load(new FileInputStream(path + file)); // 加载log4j.properties
				prop.setProperty("log4j.appender.D.File", root1); // 设置日志文件的输出路径
				prop.setProperty("log4j.appender.E.File", root2); // 设置日志文件的输出路径
				PropertyConfigurator.configure(prop); // 加载配置项
			} catch (Exception e) {
				System.out.println("any exception??");
				logger.info("初始化log4j日志输入路径异常,请检查web.xml参数配置是否正常,异常发生在" + this.getClass().getName()
						+ "类的public void init()方法,异常的愿意是:" + e.getMessage(), e.fillInStackTrace());
			}
		}
	}

	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	}

}

最后附上download接口的实现:(在之前一篇博文我有详细介绍,这里就不详细介绍了)

扫描二维码关注公众号,回复: 149677 查看本文章
@Controller
public class FilesController {

	@RequestMapping(value = "/download")
	public void download(HttpServletRequest request, HttpServletResponse response) throws Exception {

		String zipBasePath = request.getSession().getServletContext().getRealPath("/logs");
		System.out.println("starting download...");

		/* 判断文件夹是否有文件,遍历文件夹中的文件。。。 */
		String path = zipBasePath;
		Vector<String> vecFile = new Vector<String>();
		recursion(path, vecFile);
		System.out.println("文件路径分别是:");
		for (String fileName : vecFile) {
			System.out.println(fileName);
		}

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

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

		/* 根据临时的zip压缩包路径,创建zip文件 */
		File zip = new File(zipFilePath);
		if (!zip.exists()) {
			zip.createNewFile();
		}
		System.out.println("create the  zip file successfully...");

		/* 创建zip文件输出流 */
		FileOutputStream fos = new FileOutputStream(zip);
		ZipOutputStream zos = new ZipOutputStream(fos);
		System.out.println("create the empty zip stream successfully....");

		/* 循环读取文件路径集合,获取每一个文件的路径(将文件一个一个进行压缩) */
		for (String fp : vecFile) {
			File f = new File(fp); // 根据文件路径创建文件
			zipFile(f, zos); // 将每一个文件写入zip文件包内,即进行打包
		}
		zos.close();
		System.out.println("files zipped over, starting to download");

		/* 将打包后的文件写到客户端,有两种方法可以实现(下面会进行介绍),这里使用缓冲流输出 */
		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 download successfully");

		// 释放和关闭输入输出流
		out.flush();
		out.close();
		fis.close();
	}

	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();
		}
	}

	public void recursion(String root, Vector<String> vecFile) {
		String path = root;
		File file = new File(root);
		if (file.exists()) {
			System.out.println("this file is exit!");

			File[] subFile = file.listFiles();
			for (int i = 0; i < subFile.length; i++) {
				if (subFile[i].isDirectory()) {
					recursion(subFile[i].getAbsolutePath(), vecFile);
				} else {
					String filename = subFile[i].getName();
					vecFile.add(path + File.separator + filename);
				}
			}
		} else {
			System.out.println("this file is not exit!");
		}

	}

} 

最后总结一下编程过程中遇到一些困难以及解决方法:

1. 在编写Spring的applicationContext.xml文件时,无缘无辜出现了:

cvc-complex-type.2.3: Element 'beans' cannot have character [children], because the type's content type is element-only.错误。


错误原因:Spring在初始化的时候无法识别applicationContext.xml中的元素。

可能产生该错误的原因:网上复制的代码直接粘贴到了xml文件中,而网上的代码可能不符合xml规范


解决办法:1.去掉xml文件中的中文注解,因为复制的有些注解Spring不能识别。 

                  2.若仍然有错,则尝试修改多余的空格,因为中文空格Spring有可能识别错误。

                  3.最后的绝招:重新手动抄写一遍文件内容,保存。

参考博文:https://blog.csdn.net/mafan121/article/details/43266733

2. 在配置web.xml 文件中对配置的元素不是很熟悉:


        可以看到,在配置Servlet时,有两个地方需要配置,一个是<servlet>,另一个是<servlet-Mapping>,这两个一个是配置Servlet,一个是配置其映射信息,其中<servlet>中的<servlet-name>可以随意指定,但要有一定的意义,一般取为类的名称,例如我的类名为ServletDemo,这里取名为ServletDemo,下面的<servlet-class>是类的全路径,package+calssname,一定要是全路径!

        <servlet-Mapping>是映射信息,它也有一个<servlet-name>,里面的名字是对应的Servlet名,也就是我们上面配置的Servlet名字,这里是ServletDemo,下面的是映射路径,也就是访问Servlet的名称,这里也是以方便和有意义为前提的,是我们在访问Servlet在浏览器地址栏后面输入的那个信息,例如我的映射路径命名为/servlet,在地址栏中输入http://localhost/20170323/servlet

注意:这里的映射路径一定不能丢掉/,否则就会出错了,一定要写成/servlet,不能是servlet。



参考博文:https://blog.csdn.net/m0_37630602/article/details/65443660

3. 

eclipse项目一直显示有错,但是一直找不到错误在哪里

这天在写项目的时候碰到了这么个问题,项目上一直提示着红叉,但不管是文件里还是java buildpath里都找不到报错,然后我就郁闷了。

后来给我找到一个解决方案,能查看当前错误是什么: 

eclipse–>Window–>show View–>Markers,出现一个面板,然后在这个面板里就能查看到底是什么在出错啦。

参考博文:https://blog.csdn.net/zhagzheguo/article/details/51660908

4. 


参考博文:http://lpcjrflsa.iteye.com/blog/1101796(Log4j日志文件输出为相对路径的解决方法
 

猜你喜欢

转载自blog.csdn.net/weixin_37766296/article/details/80149351
今日推荐