100分,收集上传下载的资料 jspSmartUpload不行吗?下载地址: http://www.jspsmart.com 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 最好读一下tcp/ip协议,最重要的是http协议tcp/ip协议卷一,卷2,卷3 也不至于这么低层吧我的目的,只想写一个,同jspSmartUpload一样功能的程序。。 客戶端<input type = file>可以上传数据流服务端接受数据流,然后写但是不好的是,一次只是能上传一个文件 Commons是Apache开放源代码组织中的一个Java子项目Fileupload就是其中用来处理HTTP文件上传的子项目。 jspSmartUpload为什么觉得不好? JSP/SERVLET中关于文件上传的讨论已经很久了,网上的例程也很多,但大多都不系统,且限制很多,不能作为一个通用组件拿来既用,所以对大多数人来讲,仍然是一个很头疼的问题,究其原因,关键是JSP/SERVLET中并没有给出一个实现文件上传的标准方法,本文拟从原理的角度来系统阐述JSP/SERVLET的上传原理,并给出一个标准实现方法。JSP/SERVLET上载的难点1、支持任意格式、任意数量的文件上载;2、上载控制的实现;3、表单信息的取得;4、“即插即用”的应用方法;我个人认为,制约通用 上载组件的实现主要是这四个难点。JSP/SERVLET上传的原理JSP/SERVLET文件 上载是通过ServletInputStream类来实现的,ServletInputStream类是java.io.InputStream的一个扩展抽象类,实质上也是一个输入流,通过ReadLine方法从Request端一行一行读取,可见,JSP/SERVLET上载根本上是用流来实现的,理解了这个就不难理解整个 上载的原理。ServletInputStream实现文件 上载必须采用HTTP POST 或者HTTP PUT协议,HTTP GET协议只能传递很少的数据,是不能实现文件上载的。下面我们来看一下上传的数据流的结构,首先要在BROWSER端给出一个请求,我们的请求如下(文件名为test1.jsp):<%@ page contentType="text/html; charset=GBK" %><html><head><title>文件上载</title></head><body><form action="test2.jsp" enctype="MULTIPART/FORM-DATA" method=post>说明一: <input type="text" name="explain1" /><br />说明二: <input type="text" name="explain2" /><br />请选择上载文件1 <input type="file" name="file1" /><br />请选择上载文件2 <input type="file" name="file2" /><br />说明三: <input type="text" name="explain3" /><br /><input type="submit" value=" 上 载 " /></form></body></html> 显示如下:说明一: 说明二:请选择上载文件一:请选择上载文件二:说明三:在上载请求页中混杂了表单的三个输入框,及两个上载文件,当然输入框可以更多、更杂,可以有选择框、单选及多选按钮,待上传的文件也可以有三个、四个或所需要的更多。action="test2.jsp"表示表单将提交到"test2.jsp",另外注意表单属性中必须要有这句:enctype="MULTIPART/FORM-DATA",enctype指定 Form 输入资料的编码方式,“method”属性必须为“post”,这样表单才能提交大量数据,也表示本表单的数据传递将用流操作,“method=get”表示数据将通过地址栏进行传递,虽然方便快捷,但只适合很少的数据量。响应端“test2.jsp”页面如下:<%@ page contentType="text/html; charset=GBK" %><html><head><title>文件上载</title></head><body><jsp:useBean id="upBean" scope="page" class="com.upload.UpBean"/><%upBean.doUpload(request);out.println("上载已完成,请查看输出文件");%></body></html> test2.jsp收到请求后,调用一个java bean执行doUpload(request)操作,本操作将完成流(unicode格式)的接收并不做任何处理地将流顺序写入一个文本文件里,读写操作中用了一个缓冲区byte[] readByte,用了一个ServletInputStream 的一个方法readLine(byte[] b, int off,int len)方法读取流,请大家注意,ServletInputStream 流的readLine方法是一次读入指定大小的行,java bean (UpBean.java)代码如下:package com.upload;import java.io.*;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.ServletInputStream;public class UpBean {public void doUpload(HttpServletRequest req) throws ServletException, IOException{//首先定义一个文本文件File file = new File("out.txt");//readCount 记录从输入流中实际读取的字符数int readCount;//输入流缓冲区byte[] readByte = new byte[1024];//初始化输入流ServletInputStream servletInputStream = req.getInputStream();//初始化一个输出流(到文件)FileOutputStream fileOutputStream = new FileOutputStream(file);//循环从读取输入流中读取字节readCount = servletInputStream.readLine(readByte, 0,readByte.length);while(readCount != -1){fileOutputStream.write(readByte,0,readCount);readCount = servletInputStream.readLine(readByte, 0, 1024);}//关闭文件流fileOutputStream.flush();}} 为了便于我们阅读流,上载的两个文件为两个简单的文本文件(有格式的文件,不便于直接分析):one.txt及two.txt,文件内容如下,实验时请建立对应文本文件,内容请直接copy以下所示: one.txt:one one oneone one one two.txttwotwo twotwo two two 都准备好以后,我们就可以运行了,运行时请注意,文本部分及文件部分最好不要出现汉字,或其他双字符集字符,尽量采用英文,因为接收是采用的Unicode字符集,我们未对输入做任何处理。 我们在三个输入框输入的字符为,说明一:explain1;说明二:explain2;说明三:explain3,out.txt接收到如下字符:-----------------------------7d2623a3e0286Content-Disposition: form-data; name="explain1"explain1-----------------------------7d2623a3e0286Content-Disposition: form-data; name="explain2"explain2-----------------------------7d2623a3e0286Content-Disposition: form-data; name="file1"; filename="C:\test\one.txt"Content-Type: text/plainone one oneone one one-----------------------------7d2623a3e0286Content-Disposition: form-data; name="file2"; filename="C:\test\two.txt"Content-Type: text/plaintwotwo twotwo two two-----------------------------7d2623a3e0286Content-Disposition: form-data; name="explain3"explain3-----------------------------7d2623a3e0286-- 可以很明显的看到,out.txt被“-----------------------------7d2623a3e0286”分成了五 节,即表单的每个输入部分都对应一节,结尾部分是“-----------------------------7d2623a3e0286--”,刚好比开始的一段字符在最后多出两个“-”, 每节的第一行是输入内容的说明“Content-Disposition: form-data”,“name="explain1"”表示 上载请求项的name,文本输入部分仅这两个说明,如果输入的是文件还用两项说明:“filename="C:\test\one.txt"”,表示输入源,基于ms-windows的ie上载带有完整的路径,netscape及其他浏览器可能只有一个文件名;还有一项是关于输入格式的“Content-Type: text/plain”;表示输入格式是文本类型,如果我们上载的是bmp文件则为“Content-Type: image/bmp”,word文件为“application/msword”...,说明的下面紧接着是一个空行,然后下面才是我们所需的内容。 仔细分析未加修改的输入流格式,有助于我们实现文件与输入文本的准确分离。 通过以上的分析可以看出,准确分离上载的文件及文本信息需要以下要素:1、数据段分割符、结束符(比分割符多出两个“-”);2、输入文本及上载的文件区分标志(文本为“name=”,文件为“filename=”);3、编码格式,可以通过HttpServletRequest 类getCharacterEncoding() 方法取得。4、表单文本部分名称及内容,名称为“name=”后面的字符,内容为该段第三行及以后的内容;5、文件名称及内容,名称为“filename=”后面的字符,内容为该段第三行及以后的内容。 下面我们将讨论输入流的分离。 程序实现分析 我们首先画出程序实现的主体结构图,请注意判断文件标志(indexOf("filename=")>0),与判断文本标志(indexOf("name=")>0)的顺序,当(indexOf("filename=")>0)成立时,(indexOf("name=")>0)一定也是成立的,所以判断文件要在判断文本前。 分离文件及输入文本,为完整保存上载的文件信息及输入的文本信息,本程序建立了两个类:public class FileInfo 、public class InputField,及两个线性表private ArrayList upFilesList、private ArrayList inputFieldList,用于动态增加文件信息及文本信息,定义如下: FileInfo.java(记录上载文件信息)package com.upload; public class FileInfo {private String fileName;private boolean validFlag;private String filePath;private long fileSize;//设置文件信息//上载文件是否有效标志public void setValidFlag(boolean validFlag){this.validFlag = validFlag;}//文件名public void setFileName(String filename){this.fileName = filename;}//存贮路径public void setFilePath(String filePath){this.filePath = filePath;}//文件大小public void setFileSize(long fileSize){this.fileSize = fileSize;}//上载文件是否有效标志public boolean getValidFlag(){return validFlag;}//取得文件名public String getFileName(){return fileName;}//取得存贮路径public String getFilePath() {return filePath;}//取得文件大小public long getFileSize(){return fileSize;}} InputField.java(记录输入文本信息)package comupload;public class InputField{private String inputName; //输入框名private String inputContent; //输入框内容//设置输入框名称及内容public void setInputName(String inputName){this.inputName = inputName;}public void setInputContent(String inputContent){this.inputContent = inputContent;}//返回输入框名称及内容public String getInputName(){return inputName;}public String getInputContent(){return inputContent;}} private ArrayList upFilesList = new ArrayList(); //上载文件信息链表 private ArrayList inputFieldList = new ArrayList(); //输入文本信息链表 分离文件及及分离文本输入的流程图如下: 对于框图更详细的描述请大家自己去做,需要指出的是,在输入流中,每个自然换行段或每节内容的尾部都还有两个特殊的字符“/r/n”即换行回车符,当我们取得输入内容时一定要考虑到这两个字符,不然得不到正确的结果,以下是过滤文件名的程序段:filename = line.substring(i + 10,line.length() - 3);filename = getFileName(filename); line是文件名所在行的整行内容,i是 “filename=”在此行中的位置,最后减三个字符,除了“\r\n”还减去了一个冒号“"”,第一句运行后,取得的是带完整路径的文件名,第二行是分离单纯文件名的子程序。 取得文件内容最后一行的程序段为: //对最后一行进行处理if(line != null && writeByte[0] != 45 && writeCount[0] > 2)fileOutputStream.write(writeByte, 0, writeCount[0] - 2);if(lineContent != null && readByte[0] != 45 && readCount[0] > 2)fileOutputStream.write(readByte, 0, readCount[0] - 2); 东西没发全,CSDN 不让这样发东西。到密码:8029983 关于struts2页面跳转问题 POI修改excel保存后出错! JDBC驱动连接SQL SERVER2005的问题 jsp初学者 求教 求助:javamail邮件发送问题 apache2.2+tomcat5.5整合后directoryindex的问题 关于相对路径 请高手帮忙:如何跟踪访问WEB应用的用户 给我一个解答好吗? 火狐提示 纯文本文件的字符编码未声明。如果该文件包含 US-ASCII 范围之外的字符,该文件将在某些浏览器配置中呈现为乱码。该文件的字符编码需要在传输协议层 jsp 简单问题 javabean 的构造函数能自动运行吗?马上给分
tcp/ip协议卷一,卷2,卷3
也不至于这么低层吧
我的目的,只想写一个,同jspSmartUpload一样功能的程序。。
<input type = file>
可以上传数据流
服务端接受数据流,然后写
但是不好的是,一次只是能上传一个文件
Fileupload就是其中用来处理HTTP文件上传的子项目。
JSP/SERVLET上载的难点
1、支持任意格式、任意数量的文件上载;2、上载控制的实现;3、表单信息的取得;4、“即插即用”的应用方法;我个人认为,制约通用 上载组件的实现主要是这四个难点。
JSP/SERVLET上传的原理
JSP/SERVLET文件 上载是通过ServletInputStream类来实现的,ServletInputStream类是java.io.InputStream的一个扩展抽象类,实质上也是一个输入流,通过ReadLine方法从Request端一行一行读取,可见,JSP/SERVLET上载根本上是用流来实现的,理解了这个就不难理解整个 上载的原理。ServletInputStream实现文件 上载必须采用HTTP POST 或者HTTP PUT协议,HTTP GET协议只能传递很少的数据,是不能实现文件上载的。
下面我们来看一下上传的数据流的结构,首先要在BROWSER端给出一个请求,我们的请求如下(文件名为test1.jsp):
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>文件上载</title>
</head>
<body>
<form action="test2.jsp" enctype="MULTIPART/FORM-DATA" method=post>
说明一: <input type="text" name="explain1" />
<br />
说明二: <input type="text" name="explain2" />
<br />
请选择上载文件1 <input type="file" name="file1" />
<br />
请选择上载文件2 <input type="file" name="file2" />
<br />
说明三: <input type="text" name="explain3" />
<br />
<input type="submit" value=" 上 载 " />
</form>
</body>
</html>
显示如下:
说明一:
说明二:
请选择上载文件一:
请选择上载文件二:
说明三:
在上载请求页中混杂了表单的三个输入框,及两个上载文件,当然输入框可以更多、更杂,可以有选择框、单选及多选按钮,待上传的文件也可以有三个、四个或所需要的更多。
action="test2.jsp"表示表单将提交到"test2.jsp",另外注意表单属性中必须要有这句:enctype="MULTIPART/FORM-DATA",enctype指定 Form 输入资料的编码方式,“method”属性必须为“post”,这样表单才能提交大量数据,也表示本表单的数据传递将用流操作,“method=get”表示数据将通过地址栏进行传递,虽然方便快捷,但只适合很少的数据量。
响应端“test2.jsp”页面如下:
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>文件上载</title>
</head>
<body>
<jsp:useBean id="upBean" scope="page" class="com.upload.UpBean"/>
<%
upBean.doUpload(request);
out.println("上载已完成,请查看输出文件");
%>
</body>
</html>
test2.jsp收到请求后,调用一个java bean执行doUpload(request)操作,本操作将完成流(unicode格式)的接收并不做任何处理地将流顺序写入一个文本文件里,读写操作中用了一个缓冲区byte[] readByte,用了一个ServletInputStream 的一个方法readLine(byte[] b, int off,int len)方法读取流,请大家注意,ServletInputStream 流的readLine方法是一次读入指定大小的行,java bean (UpBean.java)代码如下:
package com.upload;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletInputStream;public class UpBean {public void doUpload(HttpServletRequest req) throws ServletException, IOException{
//首先定义一个文本文件
File file = new File("out.txt");
//readCount 记录从输入流中实际读取的字符数
int readCount;
//输入流缓冲区
byte[] readByte = new byte[1024];
//初始化输入流
ServletInputStream servletInputStream = req.getInputStream();
//初始化一个输出流(到文件)
FileOutputStream fileOutputStream = new FileOutputStream(file);
//循环从读取输入流中读取字节
readCount = servletInputStream.readLine(readByte, 0,readByte.length);
while(readCount != -1){
fileOutputStream.write(readByte,0,readCount);
readCount = servletInputStream.readLine(readByte, 0, 1024);
}
//关闭文件流
fileOutputStream.flush();
}
}
为了便于我们阅读流,上载的两个文件为两个简单的文本文件(有格式的文件,不便于直接分析):one.txt及two.txt,文件内容如下,实验时请建立对应文本文件,内容请直接copy以下所示: one.txt:one
one one
one one one two.txttwo
two two
two two two 都准备好以后,我们就可以运行了,运行时请注意,文本部分及文件部分最好不要出现汉字,或其他双字符集字符,尽量采用英文,因为接收是采用的Unicode字符集,我们未对输入做任何处理。 我们在三个输入框输入的字符为,说明一:explain1;说明二:explain2;说明三:explain3,out.txt接收到如下字符:-----------------------------7d2623a3e0286
Content-Disposition: form-data; name="explain1"explain1
-----------------------------7d2623a3e0286
Content-Disposition: form-data; name="explain2"explain2
-----------------------------7d2623a3e0286
Content-Disposition: form-data; name="file1"; filename="C:\test\one.txt"
Content-Type: text/plainone
one one
one one one
-----------------------------7d2623a3e0286
Content-Disposition: form-data; name="file2"; filename="C:\test\two.txt"
Content-Type: text/plaintwo
two two
two two two
-----------------------------7d2623a3e0286
Content-Disposition: form-data; name="explain3"explain3
-----------------------------7d2623a3e0286--
可以很明显的看到,out.txt被“-----------------------------7d2623a3e0286”分成了五 节,即表单的每个输入部分都对应一节,结尾部分是“-----------------------------7d2623a3e0286--”,刚好比开始的一段字符在最后多出两个“-”, 每节的第一行是输入内容的说明“Content-Disposition: form-data”,“name="explain1"”表示 上载请求项的name,文本输入部分仅这两个说明,如果输入的是文件还用两项说明:“filename="C:\test\one.txt"”,表示输入源,基于ms-windows的ie上载带有完整的路径,netscape及其他浏览器可能只有一个文件名;还有一项是关于输入格式的“Content-Type: text/plain”;表示输入格式是文本类型,如果我们上载的是bmp文件则为“Content-Type: image/bmp”,word文件为“application/msword”...,说明的下面紧接着是一个空行,然后下面才是我们所需的内容。 仔细分析未加修改的输入流格式,有助于我们实现文件与输入文本的准确分离。 通过以上的分析可以看出,准确分离上载的文件及文本信息需要以下要素:1、数据段分割符、结束符(比分割符多出两个“-”);2、输入文本及上载的文件区分标志(文本为“name=”,文件为“filename=”);3、编码格式,可以通过HttpServletRequest 类getCharacterEncoding() 方法取得。4、表单文本部分名称及内容,名称为“name=”后面的字符,内容为该段第三行及以后的内容;5、文件名称及内容,名称为“filename=”后面的字符,内容为该段第三行及以后的内容。 下面我们将讨论输入流的分离。 程序实现分析 我们首先画出程序实现的主体结构图,请注意判断文件标志(indexOf("filename=")>0),与判断文本标志(indexOf("name=")>0)的顺序,当(indexOf("filename=")>0)成立时,(indexOf("name=")>0)一定也是成立的,所以判断文件要在判断文本前。
分离文件及输入文本,为完整保存上载的文件信息及输入的文本信息,本程序建立了两个类:public class FileInfo 、public class InputField,及两个线性表private ArrayList upFilesList、private ArrayList inputFieldList,用于动态增加文件信息及文本信息,定义如下: FileInfo.java(记录上载文件信息)package com.upload; public class FileInfo {
private String fileName;
private boolean validFlag;
private String filePath;
private long fileSize;
//设置文件信息
//上载文件是否有效标志
public void setValidFlag(boolean validFlag){
this.validFlag = validFlag;
}
//文件名
public void setFileName(String filename){
this.fileName = filename;
}
//存贮路径
public void setFilePath(String filePath){
this.filePath = filePath;
}
//文件大小
public void setFileSize(long fileSize){
this.fileSize = fileSize;
}
//上载文件是否有效标志
public boolean getValidFlag(){
return validFlag;
}
//取得文件名
public String getFileName(){
return fileName;
}
//取得存贮路径
public String getFilePath() {
return filePath;
}
//取得文件大小
public long getFileSize(){
return fileSize;
}
}
InputField.java(记录输入文本信息)package comupload;public class InputField{
private String inputName; //输入框名
private String inputContent; //输入框内容
//设置输入框名称及内容
public void setInputName(String inputName){
this.inputName = inputName;
}
public void setInputContent(String inputContent){
this.inputContent = inputContent;
}
//返回输入框名称及内容
public String getInputName(){
return inputName;
}
public String getInputContent(){
return inputContent;
}
} private ArrayList upFilesList = new ArrayList(); //上载文件信息链表
private ArrayList inputFieldList = new ArrayList(); //输入文本信息链表
分离文件及及分离文本输入的流程图如下: 对于框图更详细的描述请大家自己去做,需要指出的是,在输入流中,每个自然换行段或每节内容的尾部都还有两个特殊的字符“/r/n”即换行回车符,当我们取得输入内容时一定要考虑到这两个字符,不然得不到正确的结果,以下是过滤文件名的程序段:filename = line.substring(i + 10,line.length() - 3);
filename = getFileName(filename); line是文件名所在行的整行内容,i是 “filename=”在此行中的位置,最后减三个字符,除了“\r\n”还减去了一个冒号“"”,第一句运行后,取得的是带完整路径的文件名,第二行是分离单纯文件名的子程序。 取得文件内容最后一行的程序段为: //对最后一行进行处理
if(line != null && writeByte[0] != 45 && writeCount[0] > 2)
fileOutputStream.write(writeByte, 0, writeCount[0] - 2);if(lineContent != null && readByte[0] != 45 && readCount[0] > 2)
fileOutputStream.write(readByte, 0, readCount[0] - 2);
到
密码:8029983