自己尝试实现的文件上传功能
程序员文章站
2022-07-01 17:02:56
...
今天偶然想自己实现一下文件上传功能,但又不知从何入手,于是打算走一步算一步。
获得request的输入流,将其完全输出,发现里面的内容格式是类似于这样的:
-----------------------------7d81853a1055a
Content-Disposition:form-data;name="first"
FirstPara
-----------------------------7d81853a1055a
Content-Disposition:form-data;name="file";filename="C://DocumentsandSettings//RayChase//桌面//Try.txt"
Content-Type:text/plain
TRY
-----------------------------7d81853a1055a
Content-Disposition:form-data;name="last"
LastPara
-----------------------------7d81853a1055a--
Content-Disposition:form-data;name="first"
FirstPara
-----------------------------7d81853a1055a
Content-Disposition:form-data;name="file";filename="C://DocumentsandSettings//RayChase//桌面//Try.txt"
Content-Type:text/plain
TRY
-----------------------------7d81853a1055a
Content-Disposition:form-data;name="last"
LastPara
-----------------------------7d81853a1055a--
其中的双斜杠应该为单斜杠。这样一来我就有思路了:
文件参数之前有个表单参数first,之后有个表单参数last,而分隔这三者的皆是被我称为“分隔符”的东西,即是那个"-----------------------------7d81853a1055a"这样的内容,那么我想我先获取分隔符,然后从那一串filename="......"中获取文件名Try.txt,并从下面一行的Content-Type的后面获取浏览器认定的文件类型,再跳过一个空行,下面就是文件内容了,接着分隔符则标志着文件内容的结束。由此,我就可以依据解析的文件名建立文件,再将对应的文件内容写入了。
那就来尝试一下吧。后来找了几个算法,都有个问题,就是在输入文件内容后总会多加上一个回车换行符(源于request擅自添加的);而我的实现倒是没有这个问题。
packagecom.XiongYi.file;
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjavax.servlet.ServletException;
importjavax.servlet.ServletInputStream;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassUploadGroupwareextendsHttpServlet{
/**
*ThedoGetmethodoftheservlet.<br>
*
*Thismethodiscalledwhenaformhasitstagvaluemethodequalstoget.
*
*@paramrequesttherequestsendbytheclienttotheserver
*@paramresponsetheresponsesendbytheservertotheclient
*@throwsServletExceptionifanerroroccurred
*@throwsIOExceptionifanerroroccurred
*/
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
doPost(request,response);
}
/**
*ThedoPostmethodoftheservlet.<br>
*
*Thismethodiscalledwhenaformhasitstagvaluemethodequalstopost.
*
*@paramrequesttherequestsendbytheclienttotheserver
*@paramresponsetheresponsesendbytheservertotheclient
*@throwsServletExceptionifanerroroccurred
*@throwsIOExceptionifanerroroccurred
*/
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
System.out.println(request.getParameter("first"));
System.out.println(request.getParameter("file"));
//jsp页面中加入了enctype="multipart/form-data"
//那么这两句话是没有用的,只能输出null。
ServletInputStreamsis=request.getInputStream();
bytebuf[]=newbyte[1024];
intnum;
Strings;
Stringtype=null;
Stringpagination=null;
//分隔符。比如:-----------------------------7d83152f30556
while((num=sis.readLine(buf,0,buf.length))!=-1){
//readLine的第三个参数和read方法的第三个参数不同,
//read方法第三个参数若为-1表示取到流末尾,
//readLine方法则不能这么用。
if(pagination==null)
pagination=newString(buf,0,num);
s=newString(buf,0,num,"GBK");
if(s.startsWith("Content-Disposition:")){
//可能会出现文件
StringnextS;//下一行
num=sis.readLine(buf,0,buf.length);
nextS=newString(buf,0,num,"GBK");
if(!nextS.startsWith("Content-Type:"))
continue;//看来不是文件,继续吧
type=nextS.substring(nextS.indexOf("")+1);
//读取上传文件类型信息
System.out.println(type);
Stringname=s.substring(s.lastIndexOf("/")+1,s.length()-3);
//取出名字来
System.out.println(name);
Filefile=newFile("./upload/"+name);
FileOutputStreamfos=newFileOutputStream(file);
sis.readLine(buf,0,buf.length);//跳过空行
bytebuf2[]=newbyte[1024];
//再准备一个相同大小的缓冲数组是为了交替使用,
//以便在发现文件结束时避免输出最末两个字节(回车换行符),
//而这最末的两个字节是request自己加上的!
intnum2=0;
booleanwhichBuf=true;
//确定使用哪个缓冲数组
while(num!=-1&&num2!=-1){
if(whichBuf){
num=sis.readLine(buf,0,buf.length);
s=newString(buf,0,num,"GBK");
if(s.startsWith(pagination)){
if(num2>=2)
num2=num2-2;
fos.write(buf2,0,num2);
num=-1;//写完了
}else{
fos.write(buf2,0,num2);
}
}else{
num2=sis.readLine(buf2,0,buf2.length);
s=newString(buf2,0,num2,"GBK");
if(s.startsWith(pagination)){
if(num>=2)
num=num-2;
fos.write(buf,0,num);
num2=-1;//写完了
}else{
fos.write(buf,0,num);
}
}//else
whichBuf=!whichBuf;
}//while
fos.close();
}//if
}//while
sis.close();
}//doPost
}
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjavax.servlet.ServletException;
importjavax.servlet.ServletInputStream;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassUploadGroupwareextendsHttpServlet{
/**
*ThedoGetmethodoftheservlet.<br>
*
*Thismethodiscalledwhenaformhasitstagvaluemethodequalstoget.
*
*@paramrequesttherequestsendbytheclienttotheserver
*@paramresponsetheresponsesendbytheservertotheclient
*@throwsServletExceptionifanerroroccurred
*@throwsIOExceptionifanerroroccurred
*/
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
doPost(request,response);
}
/**
*ThedoPostmethodoftheservlet.<br>
*
*Thismethodiscalledwhenaformhasitstagvaluemethodequalstopost.
*
*@paramrequesttherequestsendbytheclienttotheserver
*@paramresponsetheresponsesendbytheservertotheclient
*@throwsServletExceptionifanerroroccurred
*@throwsIOExceptionifanerroroccurred
*/
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
System.out.println(request.getParameter("first"));
System.out.println(request.getParameter("file"));
//jsp页面中加入了enctype="multipart/form-data"
//那么这两句话是没有用的,只能输出null。
ServletInputStreamsis=request.getInputStream();
bytebuf[]=newbyte[1024];
intnum;
Strings;
Stringtype=null;
Stringpagination=null;
//分隔符。比如:-----------------------------7d83152f30556
while((num=sis.readLine(buf,0,buf.length))!=-1){
//readLine的第三个参数和read方法的第三个参数不同,
//read方法第三个参数若为-1表示取到流末尾,
//readLine方法则不能这么用。
if(pagination==null)
pagination=newString(buf,0,num);
s=newString(buf,0,num,"GBK");
if(s.startsWith("Content-Disposition:")){
//可能会出现文件
StringnextS;//下一行
num=sis.readLine(buf,0,buf.length);
nextS=newString(buf,0,num,"GBK");
if(!nextS.startsWith("Content-Type:"))
continue;//看来不是文件,继续吧
type=nextS.substring(nextS.indexOf("")+1);
//读取上传文件类型信息
System.out.println(type);
Stringname=s.substring(s.lastIndexOf("/")+1,s.length()-3);
//取出名字来
System.out.println(name);
Filefile=newFile("./upload/"+name);
FileOutputStreamfos=newFileOutputStream(file);
sis.readLine(buf,0,buf.length);//跳过空行
bytebuf2[]=newbyte[1024];
//再准备一个相同大小的缓冲数组是为了交替使用,
//以便在发现文件结束时避免输出最末两个字节(回车换行符),
//而这最末的两个字节是request自己加上的!
intnum2=0;
booleanwhichBuf=true;
//确定使用哪个缓冲数组
while(num!=-1&&num2!=-1){
if(whichBuf){
num=sis.readLine(buf,0,buf.length);
s=newString(buf,0,num,"GBK");
if(s.startsWith(pagination)){
if(num2>=2)
num2=num2-2;
fos.write(buf2,0,num2);
num=-1;//写完了
}else{
fos.write(buf2,0,num2);
}
}else{
num2=sis.readLine(buf2,0,buf2.length);
s=newString(buf2,0,num2,"GBK");
if(s.startsWith(pagination)){
if(num>=2)
num=num-2;
fos.write(buf,0,num);
num2=-1;//写完了
}else{
fos.write(buf,0,num);
}
}//else
whichBuf=!whichBuf;
}//while
fos.close();
}//if
}//while
sis.close();
}//doPost
}
经试验上传各种类型的文件(包括图片、文本等)都没有问题。
如果有其他或者优化的方法,请不吝赐教。
上一篇: 处理hadoop发送的文件到后台并解析存储到数据库策略
下一篇: c#属性1(Property)