很久以前做文件下载都是在服务器生成文件,然后做一个链接,这样浏览器不认识的文件类型就会弹出操作系统另存对话框,实现下载,今天遇到一个案例被困了,具体需求是这样:
在web页面点击下载按钮,服务端从数据库查询数据,组装成输出流,由response输出到客户端,由于架构中使用的第三方组建较多,所以在做这个功能时让人头疼,最终在ahuaxuan的帮助下搞定,现将代码贴出来供兄弟们参考:
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();
}
}
以上代码尽供参考,有更好的意见或方法请赐教。