当前位置:编程问答 > JSP >

自己尝试实现的文件上传功能(未用其他组件)

今天偶然想自己实现一下文件上传功能,但又不知从何入手,于是打算走一步算一步。

获得request的输入流,将其完全输出,发现里面的内容格式是类似于这样的:



-----------------------------7d81853a1055a
Content-Disposition: form-data; name="first"

FirstPara
-----------------------------7d81853a1055a
Content-Disposition: form-data; name="file"; filename="C:\Documents and Settings\Ray Chase\桌面\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擅自添加的);而我的实现倒是没有这个问题。



package com.XiongYi.file;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class UploadGroupware extends HttpServlet {

    
/**
     * The doGet method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to get.
     * 
     * 
@param request the request send by the client to the server
     * 
@param response the response send by the server to the client
     * 
@throws ServletException if an error occurred
     * 
@throws IOException if an error occurred
     
*/

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

        doPost(request,response);
    }


    
/**
     * The doPost method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to post.
     * 
     * 
@param request the request send by the client to the server
     * 
@param response the response send by the server to the client
     * 
@throws ServletException if an error occurred
     * 
@throws IOException if an error occurred
     
*/

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

        System.out.println(request.getParameter(
"first"));
        System.out.println(request.getParameter(
"file"));
        
//jsp页面中加入了 enctype="multipart/form-data"
        
//那么这两句话是没有用的,只能输出null。
        
        ServletInputStream sis 
= request.getInputStream();
        
byte buf[] = new byte[1024];
        
int num;
        String s;
        String type 
= null;
        
        String pagination 
= null;
        
//分隔符。比如:-----------------------------7d83152f30556
        
        
while(  (num=sis.readLine(buf, 0, buf.length))!=-1  ){
                
//readLine的第三个参数和read方法的第三个参数不同,
                
//read方法第三个参数若为-1表示取到流末尾,
                
//readLine方法则不能这么用。

            
if(pagination==null)
                pagination 
= new String(buf,0,num);
            
            s 
= new String(buf,0,num,"GBK");
            
if(s.startsWith("Content-Disposition: ")){
                
//可能会出现文件
                
                String nextS;    
//下一行
                num = sis.readLine(buf, 0, buf.length);
                nextS 
= new String(buf,0,num,"GBK");
                
                
if(!nextS.startsWith("Content-Type: "))
                    
continue;    //看来不是文件,继续吧

                type 
= nextS.substring( nextS.indexOf(" ")+1 );
                
//读取上传文件类型信息
                System.out.println(type);
                
                String name 
= s.substring(s.lastIndexOf("")+1, s.length()-3);
                
//取出名字来
                System.out.println(name);
                
                File file 
= new File("./upload/"+name);
                FileOutputStream fos 
= new FileOutputStream(file);
                
                sis.readLine(buf, 
0, buf.length);    //跳过空行
                
                
byte buf2[] = new byte[1024];
                
//再准备一个相同大小的缓冲数组是为了交替使用,
                
//以便在发现文件结束时避免输出最末两个字节(回车换行符),
                
//而这最末的两个字节是request自己加上的!
                int num2=0;
                
                
boolean whichBuf = true;
                
//确定使用哪个缓冲数组
                
                
while(num!=-1 && num2!=-1){

                    
if(whichBuf){
                        num
=sis.readLine(buf, 0, buf.length);
                        s 
= new String(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 
= new String(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

}

经试验上传各种类型的文件(包括图片、文本等)都没有问题。

如果有其他或者优化的方法,请不吝赐教。



补充:Jsp教程,Java技巧及代码 
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,