很久以前做文件下载都是在服务器生成文件,然后做一个链接,这样浏览器不认识的文件类型就会弹出操作系统另存对话框,实现下载,今天遇到一个案例被困了,具体需求是这样:
在web页面点击下载按钮,服务端从数据库查询数据,组装成输出流,由response输出到客户端,由于架构中使用的第三方组件较多,所以在做这个功能时让人头疼,现将代码贴出来供兄弟们参考:
public class DownServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; @Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { byte [] picbytes = "fdsafdasfds".getBytes(); res.setContentType("application/x-download"); // attachment:打开另存对话框;inline:用浏览器打开 res.setHeader("Content-Disposition", "attachment;filename=fdsafd.txt"); //res.setHeader("Content-Disposition", "inline;filename=fdsafd.txt"); res.getOutputStream().write(picbytes); res.getOutputStream().flush(); } }
在下载应用中需要注意web.xml中是否有其他的filter和一些拦截器配置,这些可能会拦截掉下载的地址.
下面这个类是用来抓取网络上的文件,转换成字节数组,fileUrl是文件的绝对路径,在上面的Servlet中调用download()方法,然后将setHeader()方法参数改为"inline",就可将别的网站上抓取的图片输出的自己的页面。
import java.io.ByteArrayOutputStream; import java.io.InputStream; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; public class HttpDownloadService { public byte [] download(String fileUrl) { HttpClient client = new HttpClient(); GetMethod method = new GetMethod(fileUrl); client.getHttpConnectionManager().getParams().setConnectionTimeout(1000 * 60 * 5); client.getHttpConnectionManager().getParams().setSoTimeout(1000 * 60 * 10); ByteArrayOutputStream outPut = new ByteArrayOutputStream(); try { UsernamePasswordCredentials upc = new UsernamePasswordCredentials("", ""); AuthScope scope = new AuthScope(null, 0); client.getState().setCredentials(scope, upc); method.setDoAuthentication(true); int status = client.executeMethod(method); if (status != 200) { throw new RuntimeException("the status is " + status); } InputStream input = method.getResponseBodyAsStream(); int length = 0; byte [] rbody = new byte[1024]; int readNum = 0; while ((readNum = input.read(rbody)) > 0) { byte [] kk = new byte [readNum]; for (int k = 0; k < kk.length; k++) { kk[k] = rbody[k]; } outPut.write(kk); length += readNum; outPut.flush(); } outPut.flush(); outPut.close(); } catch (Exception e) { e.printStackTrace(); } finally { method.releaseConnection(); } return outPut.toByteArray(); } }
以上代码尽供参考,有更好的意见或方法请赐教。