·前言
文件下载有诸多场景,而这一般都涉及到两个部分,一是文件的请求方如何请求,二是文件的提方如何提供。
文件的获取方:
1、直接在浏览器中访问下载地址获取下载文件;
2、使用程序访问下载地址,并将文件保存到指定位置。
文件的提供方:
1、获取本地的文件,比如 d://filePackage//123.zip,对外提供一个请求的下载地址:http://www.localhost:8080/test/test.action;
2、还有一种特殊的文件提供方,直接请求别的地址返回给请求方,是作为中介存在的。准确的说,他自己也是一个文件获取方,比如服务器1上的文件不允许外网访问,服务器2可以访问服务器1同时对外网开放,
用户处于外网想要得到内网服务器1上的文件。这个时候,就需要位于服务器2上的文件提供方从文件服务器1上得到文件并直接返回给外网的请求用户了。
·场景说明
场景说明的一句是下面的代码
1、FileDown.java中有三个方法
fileSupport(),这个方法会把本地文件以流的形式返给请求方,不限制大小,不限制文件格式。可以直接在浏览器访问并下载文件。
如果使用后台java代码访问的话,就会获取到文件流了。
fileDeliver(),这个方法会请求fileSupport()这种提供文件下载的方法,然后再次把文件流返还给请求方,可以这样说,fileDeliver把第一个人的文件传递给了第三个人,也可以直接在浏览器中访问,获得文件。
fileDeliverLocal(),这个方法会把得到的文件流保存到本地指定位置。
2、请求的三个链接
http://localhost:8080/struts2go/fileDown/fileSupport.action
http://localhost:8080/struts2go/fileDown/fileDeliver.action
http://localhost:8080/struts2go/fileDown/fileDeliverLocal.action
·直接贴代码
FileDown.java
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* 本类用于测试连续流文件下载
* 流程是,服务器1提供原始文件,服务器2向服务器1请求,用户请求服务器2得到服务器1中的原始文件,文件格式为zip
* 本类将提供两个方法
* fileSupport
* fileDeliver
*
* 最终实现效果是,用户请求fileDeliver,fileDeliver请求fileSupport,最终用户得到zip文件
*
* java:FileDown.java
* http://localhost:8080/struts2go/fileDown/fileSupport.action
* struts:struts-filedown.xml
* jsp:无
* @author WuJieJecket
*
*/
@SuppressWarnings("serial")
public class FileDown extends ActionSupport {
//将本项目中的任意指定文件返回给请求方-无大小限制
public void fileSupport(){
String localAddress=ServletActionContext.getServletContext().getRealPath("EpolicyFile");//文件的相对路径,相对于项目的webapp的路径
final String fileName="20151216123456789";//文件的名字
try {
localAddress = localAddress +"/"+ fileName+ ".zip";//获得zip文件的完整路径
File file = new File(localAddress); //获得文件
InputStream ins = new BufferedInputStream(new FileInputStream(file));//获得文件的输入流
HttpServletResponse response = (HttpServletResponse) ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE);
response.reset();
response.addHeader("Content-Disposition","attachment;filename="+new String(file.getName().getBytes()));//设置header,文件名字
response.addHeader("Content-Length", "" + file.length()); //文件长度
response.setContentType("application/octet-stream");//设置文件输出类型
OutputStream ous = new BufferedOutputStream(response.getOutputStream());//设置文件输出流
/*
* 该方法对于小文件是可行的,但是对于大型文件则会出现问题
* byte[] buffer = new byte[ins.available()]; ins.read(buffer);
* ins.close(); ous.write(buffer); ous.flush(); ous.close();
*/
//适用于大文件的下载,需要注意的是,这里buffer是缓冲区,为了确保下载文件能够正常打开,需要保持为1024的倍数,否则可能造成数据因覆盖重写而损坏
byte[] buffer = new byte[1024];
int count = 0;
while ((count = ins.read(buffer)) > 0) {
ous.write(buffer, 0, count);
}
ous.flush();
ous.close();
ins.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//请求fileSupport,然后直接把文件流返回给请求fileDeliver的
public void fileDeliver() throws IOException{
String getURL="http://localhost:8080/struts2go/fileDown/fileSupport.action";
URL getUrl = new URL(getURL);
// 根据拼凑的URL,打开连接,URL.openConnection函数会根据URL的类型,
// 返回不同的URLConnection子类的对象,这里URL是一个http,因此实际返回的是HttpURLConnection
HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
// 进行连接,但是实际上get request要在下一句的connection.getInputStream()函数中才会真正发到
// 服务器
connection.setConnectTimeout(25000);
connection.setReadTimeout(25000);
connection.connect();
int status = connection.getResponseCode();
if (status == 200) {
DataInputStream ins = new DataInputStream( connection.getInputStream());
// 将文件流返回给调用本方法的请求
HttpServletResponse response = (HttpServletResponse) ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE);
response.reset();
response.addHeader("Content-Disposition", connection.getHeaderField("Content-Disposition"));// 文件名
response.addHeader("Content-Length", ""+ connection.getContentLength());// 文件长度
response.setContentType("application/octet-stream");// 以文件格式不明做出处理方式
OutputStream ous = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[1024];
int count = 0;
while ((count = ins.read(buffer)) > 0) {
ous.write(buffer, 0, count);
}
ous.flush();
ous.close();
ins.close();
} else {
System.out.println("访问异常");
}
connection.disconnect();
}
// 请求fileSupport,然后直接把文件流返回给请求fileDeliver的
public void fileDeliverLocal() throws IOException {
String getURL = "http://localhost:8080/struts2go/fileDown/fileSupport.action";//文件下载地址
String localPath="d:\\a\\";//文件保存的本地地址
URL getUrl = new URL(getURL);
// 根据拼凑的URL,打开连接,URL.openConnection函数会根据URL的类型,
// 返回不同的URLConnection子类的对象,这里URL是一个http,因此实际返回的是HttpURLConnection
HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
// 进行连接,但是实际上get request要在下一句的connection.getInputStream()函数中才会真正发到
// 服务器
connection.setConnectTimeout(25000);
connection.setReadTimeout(25000);
connection.connect();
int status = connection.getResponseCode();
if (status == 200) {
//获取文件名称
String fileName=connection.getHeaderField("Content-Disposition").split("=")[1];
DataInputStream ins = new DataInputStream(connection.getInputStream());//获取文件输入流
DataOutputStream ous = new DataOutputStream(new FileOutputStream(localPath+fileName));
byte[] buffer = new byte[1024];
int count = 0;
while ((count = ins.read(buffer)) > 0) {
ous.write(buffer, 0, count);
}
ous.flush();
ous.close();
ins.close();
} else {
System.out.println("访问异常");
}
connection.disconnect();
}
}
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
<!--struts-default-->
<package name="fileDown" extends="struts-default" namespace="/fileDown">
<!--
获得原始下载
http://localhost:8080/struts2go/fileDown/fileSupport.action
-->
<action name="fileSupport" class="com.demo.fileup.FileDown" method="fileSupport"/>
<!--中介下载,其内部向 http://localhost:8080/struts2go/fileDown fileSupport.action请求
http://localhost:8080/struts2go/fileDown/fileDeliver.action
-->
<action name="fileDeliver" class="com.demo.fileup.FileDown" method="fileDeliver"/>
<!-- 下载到本地的指定位置
http://localhost:8080/struts2go/fileDown/fileDeliverLocal.action
-->
<action name="fileDeliverLocal" class="com.demo.fileup.FileDown" method="fileDeliverLocal"/>
</package>
</struts>