您的位置:首页 > 编程语言 > Java开发

Java web中上传和下载详解(上)

2013-08-19 16:20 351 查看

Java web中上传和下载详解

文件上传:

先来看一下上传对form表单有什么要求?
必须是form表单提交。
表单中的method必须是post,不能是get
表单中的enctype的属性值必须是:multipart/form-data。当不是multipart的时候,就算<input type="file">提交的效果也和普通的text类型一样。
表单中项使用file类型

文件上传对servlet的要求?
因为表单中上传的不再是字符内容,而是字节内容。就算是上传文本文件也是一样的。所以不能使用request.getParameter(String fieldName)方法。
那使用什么呢。这个时候可以使用request.getInputStream();方法获取ServletInputStream对象,它是InputStream类的子类,这个对象对应表单的正文部分,关于正文部分下面会介绍。

关于正文部分介绍。
这个是有可以使用HTTP抓包工具,我使用的是Firebug。在Firefox进行抓包的。如下图所示:





ServletInput中就包含第二张图片的内容。可以通过以下方法得到


public void doPost(HttpServletRequest request,HttpServletResponse response)throw IOException,ServletException{
request.setCharacterEncoding("utf-8");
ServletInputStream in = request.getInputStream;
String s = IOUtils.toString(in);//Apache的commons组件中的包
System.out.println(s);//结果如下
}


执行结果如下:和抓包来的没什么区别
------WebKitFormBoundaryH06xO2noLxVFeenm
Content-Disposition: form-data; name="username"
csdn
------WebKitFormBoundaryH06xO2noLxVFeenm
Content-Disposition: form-data; name="filename"; filename="a.txt"
Content-Type: text/plain
E:\Application\workspace\exam\src\cn\itcast\day20\CountDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo2.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo3.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo4.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileFilterDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\JavaFileList.java
E:\Application\workspace\exam\src\cn\itcast\day20\PrintWriterDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\PropertiesDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SequenceDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SequenceInputStreamDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SequenceVideoDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SplitFileDemo.java
------WebKitFormBoundaryH06xO2noLxVFeenm--




上传的任务就是将这些信息解析出来如果是文件部分保存到文件中,不是文件部分该给谁给谁。

4.按照上面的上传文件中ServletInputStream流的格式我自己写了一个,只能上传文本文件的上传方法。(能力有限)
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到流对象
ServletInputStream in = request.getInputStream();
//将流中的对象写入到一个字符串中。可能使用StringBuffer更好
int len = 0;
byte buf[] = new byte[1024];
String content = "";
while((len = in.read(buf))!=-1){
content = content + new String(buf, 0, len);
}
//将内容按行分割
String[] contents = content.split("\n");
//将数组转换成数组
List<String> lists = Arrays.asList(contents);
//是否包含这个Content-Type: text/plain。也就是文本文件内容的开始了
System.out.println("执行:"+lists.contains(new String("Content-Type: text/plain")));
//获取开始和结束位置
int start = 0;
int end = 0;
for (int i=1;i<lists.size();i++) {
if(lists.get(0).equals(lists.get(i))){
end = i;
}
}

System.out.println(start+":"+end);
//将数组按开始位置和结束位置截取
List<String> fileList = lists.subList(end+4, lists.size()-1);
//保存的文件
FileWriter writer = new FileWriter("F:\\a.txt");
//遍历数组如入文件
for (String s : fileList) {
writer.write(s);
writer.write("\n");
}
writer.close();
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}


使用Apache的commons组件包实现上传(还是这个强大):

快速入门(得到的效果和上面的一样):
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取解析器工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//获得解析器
ServletFileUpload fileUpload = new ServletFileUpload(factory);
try {
//解析request
List<FileItem> items = fileUpload.parseRequest(request);
//遍历解析得到的FileItem对象
for(FileItem item : items){
//如果字段名是username
if(item.getFieldName().equalsIgnoreCase("username")){
//得到提交过来的值
System.out.println(item.getString());
//如果是这个说明是文件
}else if(item.getFieldName().equalsIgnoreCase("fileName")){
//得到提交过来的值,如果是文本文件能输出,否则是乱码
item.write(new File("F:\\","b.txt"));
}
}

} catch (Exception e) {
e.printStackTrace();
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}


完全体演示:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//解决中文文件名问题
/**
* 也可以是fileUpload.setHeaderEncoding("utf-8");优先级高
*/
request.setCharacterEncoding("utf-8");

//获取解析器工厂,在factory中设置 (1024*20,new File("F://temp");如果文件过大
//设置文件超过20kb就缓存,缓存文件是在F盘的temp文件下

DiskFileItemFactory factory = new DiskFileItemFactory();
//获得解析器
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//设置上传的全部大小,包括<input type='text'>
//		fileUpload.setSizeMax(1024*900);

//设置上传文件的大小,1024为1kb
fileUpload.setFileSizeMax(300*1024);

//		fileUpload.setHeaderEncoding("utf-8");

try {
//解析request
List<FileItem> items = fileUpload.parseRequest(request);
//遍历解析得到的FileItem对象
for(FileItem item : items){
//如果字段名是username
if(item.getFieldName().equalsIgnoreCase("username")){
//得到提交过来的值
System.out.println(item.getString());
//如果是这个说明是文件
}else if(item.getFieldName().equalsIgnoreCase("fileName")){
//得到文件名
String fileName = item.getName();
//防止有些浏览器上传文件的时候,上传文件的带盘符的绝对路径。我们只要文件名就行
int index = fileName.lastIndexOf("\\");
if(index!=-1){
fileName = fileName.substring(index+1);
}
//获取后缀名.假设我只上传静态图片格式的文件,也就是格式是jpg,bmp,png这三种。其他的都不要

index = fileName.lastIndexOf(".");
//说明没有后缀名
if(index==-1){
//一般情况是,通过request.setAttribute("msg","您上传的文件没有后缀名,请重新上传");
//转发到request.getRequestDispatcher("路径").forward(request, response);
//return;

//这里我就全输出了
System.out.println("上传的文件没有后缀名");
return;
}

String extension = fileName.substring(index+1);
//上传文件如果不是以上面三个后缀名结尾,就输出错误信息
if (!extension.equalsIgnoreCase("bmp")
&& !extension.equalsIgnoreCase("jpg")
&& !extension.equalsIgnoreCase("png")) {

System.out.println("上传的文件必须是bmp或jpg或png");
return;
}
//上传文件肯定是多个,命名也是一个问题。使用Apache的commons组件的类
fileName = getuuid()+"."+extension;

//上传的文件放到哪,只能放在WEB-INF下面.如果你下面还要放分目录的话。有很多的算法
//有按时间的,用户的,文件名的hash值的等等。看需求
//我来按时间,也就是每天一个文件夹
String timeStamp = new SimpleDateFormat("yyyy.MM.dd").format(new Date());
String savePath = this.getServletContext().getRealPath("/WEB-INF/myupload")+"\\"+timeStamp;
File f = new File(savePath);
f.mkdirs();
item.write(new File(savePath,fileName));
item.delete();//删除临时文件
}}} catch (Exception e) {if(e instanceof FileUploadBase.FileSizeLimitExceededException){System.out.println("上传文件不能大于300kb");return;}else{e.printStackTrace();}}}public static String getuuid() {return UUID.randomUUID().toString().replace("-",
"");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}



如果还要判断上传文件的宽度和高度。只需在后面加上:
File f = new File(savePath);
f.mkdirs();
File saveFile = new File(savePath,fileName);
item.write(saveFile);
item.delete();//删除临时文件

ImageIcon icon = new ImageIcon(saveFile.getAbsolutePath());
Image image = icon.getImage();
image.getHeight(null);//得到图片的高
image.getWidth(null);//得到文件的宽

//如果不满足条件
saveFile.delete();


其他类型的文件也就类似了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: