文件上传下载本质是通过Socket的字节流来传输数据的。所以,对于文件上传,我们可以从HttpRequest对象获取输入流,进而获取上传文件的内容。但是采用ServletAPI并不能获取获取对应文件的字节流,而是获取整个Socket的字节流,里面包括提交的参数、上传文件内容以及其他附加信息。
Servlet API上传文件,代码如下
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
try
{
InputStream in=request.getInputStream();
File file=new File("/Users/ssl/upload.txt");
OutputStream out=new FileOutputStream(file);
byte[] buf=new byte[1024];
int count;
while ((count=in.read(buf))!=-1)
{
out.write(buf,0,count);
}
out.close();
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
// jsp
<form action="<%=basePath%>/upload"method="post" enctype="multipart/form-data">
<input type="text" name="name"value="ssl"><br>
<input type="file"name="file"><br>
<input type="submit"value="上传">
</form>
上传原始文件的内容
服务器端保存文件的内容
通过上面的两幅图可知,使用原始ServletAPI来解析上传文件的数据,需要了解HttpRequest输入流中数据的格式,才能正确解析各个参数和上传文件的内容。
上面的示例,只是让我们了解文件上传的原理。在实际应用中,往往通过第三方库来实现文件的上传或下载,如commons-fileupload。下面是采用commons-fileupload实现的文件上传功能代码,如下
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
//获得磁盘文件条目工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//获取文件需要上传到的路径
String path=request.getSession().getServletContext().getRealPath("/WEB-INF/upload");
//如果没以下两行设置的话,上传大的文件会占用较多内存,
//设置暂时存放的存储室 , 这个存储室可以和最终存储文件的目录不同
/**
* 原理它是先存到暂时存储室,然后在真正写到对应目录的硬盘上,
* 按理来说当上传一个文件时,其实是上传了两份,第一个是以 .tem 格式的
* 然后再将其真正写到对应目录的硬盘上
*/
factory.setRepository(new File(path));
//设置缓存的大小,当上传文件的容量超过该缓存时,直接放到暂时存储室
factory.setSizeThreshold(1024*1024) ;
ServletFileUpload upload=new ServletFileUpload(factory);
try
{
List<FileItem> fileItems=upload.parseRequest(request);
for (FileItem fileItem : fileItems)
{
//普通参数,也会在fileItem中,需要进行过滤;由此可以看出多文件上传也非常容易实现
String fieldname=fileItem.getFieldName();
if ("file".equals(fieldname))
{
//获取路径名
String name=fileItem.getName() ;
//索引到最后一个反斜杠
int start = name.lastIndexOf("\\");
//获取上传文件名字
String filename = name.substring(start+1);
fileItem.write(new File("/Users/ssl",filename));
}
}
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
文件下载也是通过Socket字节流将数据传输到客户端,文件下载的步骤如下:
1) 设置响应头信息
2) 获取待下载资源的输入流;
3) 将待下载资源写入到HttpResponse对象的输出流中;
4) 关闭资源;
public class DownloadServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
publicDownloadServlet()
{
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
//防止产生乱码
String filename=URLEncoder.encode("冬天.jpeg","UTF-8");
//下载文件响应头
response.setHeader("Content-Disposition","attachment;filename="+filename);
String path=this.getServletContext().getRealPath("/resources/img/winter.jpeg");
InputStream in=new FileInputStream(new File(path));
OutputStream out=response.getOutputStream();
byte[] buf=new byte[1024];
int count=0;
while ((count=in.read(buf))!=-1)
{
out.write(buf, 0, count);
}
in.close();
out.close();
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
this.doGet(request, response);
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/sunshuolei/article/details/48141227