Java Web——文件下载getResourceAsStream()返回NULL解决方案

Posted Starzkg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Web——文件下载getResourceAsStream()返回NULL解决方案相关的知识,希望对你有一定的参考价值。

问题描述

严重: Servlet.service() for servlet [club.zstuca.demo.DownloadDemo] in context with path [/DEMOWeb] threw exception
java.lang.NullPointerException
	at club.zstuca.demo.DownloadDemo.doGet(DownloadDemo.java:48)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:660)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Unknown Source)

问题分析

文件不在WebAPP根目录下,导致找不到资源。

API

Class.getResourceAsStream(String path)

JDK设置这样的规则,是很好理解的,path不以“/”开头时,我们就能获取与当前类所在的路径相同的资源文件,而以“/”开头时可以获取classPath根下任意路径的资源。

path不以“/”开头时,默认是从当前类所在的包下面获取资源

path以“/”开头时,则是从项目的classPath根下获取资源

ClassLoader.getResourceAsStream(String path)

默认是从classpath根下获取,path不能以“/”开头,path是指类加载器的加载范围,在资源加载的过程中,使用逐级向上的委托的形式加载的,“/”表示Boot ClassLoader中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null。

ServletContext.getResourceAsStream(String path)

默认从WebAPP根目录下取资源,Tomcat下path是否以“/”开头无所谓,当然这和具体的容器实现有关。

解决方案

1、在WebAPP根目录下创建res文件夹,将资源移入此文件夹 

2、修改代码 

源代码 

package club.zstuca.demo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

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

/**
 * Servlet implementation class DownloadDemo
 */
@WebServlet("/DownloadDemo")
public class DownloadDemo extends HttpServlet 
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DownloadDemo() 
        super();
        // TODO Auto-generated constructor stub
    

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
		// TODO Auto-generated method stub
		request.setCharacterEncoding("UTF-8");
		//response.setContentType("application/octet-stream");
		response.addHeader("content-Type", "application/octet-stream" );
		String filename = request.getParameter("filename");
		response.addHeader("content-Disposition", "attachment; filename=" + filename);
		//response.getWriter().append("Served at: ").append(request.getContextPath());
		
		InputStream in = this.getServletContext().getResourceAsStream("/res/" + filename);
		
		System.out.println("res/" + filename);
		System.out.println(in);
		ServletOutputStream out = response.getOutputStream();
		byte[] bs = new byte[1024];
		int len = -1;
		while((len=in.read(bs))!=-1) 
			out.write(bs,0,len);
			
		
		out.close();	
		
	

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
		// TODO Auto-generated method stub
		doGet(request, response);
	


参考文章

http://www.imooc.com/wenda/detail/593313

https://www.cnblogs.com/lebo0425/p/6607804.html

以上是关于Java Web——文件下载getResourceAsStream()返回NULL解决方案的主要内容,如果未能解决你的问题,请参考以下文章

java上传文件获取跟目录的办法

[Java开发之路](18)关于Class.getResource和ClassLoader.getResource的路径问题

Java中getClassLoader().getResource()和getResource()的区别

java打包后getResource出错

Java:使用getClassLoader.getResource时只能用绝对路径从classpath开始找文件吗?

java程序,new ImageIcon(getClass().getResource("/images/密码登陆.jpg")),在导出jar后,jar包里面没有