java上传原理

文件的上传在本地来说就是把一个文件挪到另一个地方,对于网络来说只是目标地址是网络的地址而已。java实现的原理代码如下:
File source =new File("F:/music/一生爱你千百回.mp3");
//定义目标路径
File target =new File("D:/music",source.getName());
//开始上传
CopyFile(source,target);

//实现文件上传的核心代码
static void CopyFile (File source ,File target){
InputStream in=null;
OutputStream out=null;
in=new FileInputStream(source);
out=new FileOutputStream(target);
byte[] buf =new byte[1024*10];
int len=in.read(buf);

while(len!=-1){
out.write(buf,0,len);
len=in.read(buf);
}
}
============================================================================
下面就是手工写的一个servlet上传的一个例子:
1:控制层的代码:ServletActon.jsp

package com.test.action;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.Hashtable;

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

public class ServletAction extends HttpServlet{

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

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final int NONE=0;
        final int DATAHEADER=1;
        final int FILEDATA=2;
        final int FIELDDATA=3;
        //将请求消息的实体送到b变量中
        int TotalBytes=request.getContentLength();
        byte[] b=new byte[TotalBytes];
        String contentType=request.getContentType();//请求消息类型
        String fieldname="";                        //表单域的名称
        String fieldvalue="";                       //表单域的值
        String filename="";                         //文件名
        String boundary="";                         //分界符
        String lastboundary="";                     //结束符
        int filesize=0;                             //文件长度
        Hashtable formfields=new Hashtable();
        int pos=contentType.indexOf("boundary=");
        String fileID;  //上传的文件ID
        if(pos!=-1)     //取得分界符和结束符
        {
          pos+="boundary=".length();
          boundary="--"+contentType.substring(pos);
          lastboundary=boundary+"--";
        }
        int state=NONE;
        //得到数据输入流reqbuf
        DataInputStream in=new DataInputStream(request.getInputStream());
        in.readFully(b);
        in.close();
        String reqContent=new String(b);
        BufferedReader reqbuf=new BufferedReader(new StringReader(reqContent));
        boolean flag=true;
        int i=0;
        while(flag==true)
        {
          String s=reqbuf.readLine();
          if((s==lastboundary)||(s==null)) break;
          switch(state)
          {
             case NONE:
                if (s.startsWith(boundary))
                  {
                     state=DATAHEADER;
                     i+=1;
                  }
                  break;
             case DATAHEADER:
                pos=s.indexOf("filename=");
                if (pos==-1)
                {                           //将表单域的名字解析出来
                  pos=s.indexOf("name=");
                  pos+="name=".length()+1;
                  s=s.substring(pos);
                  int l=s.length();
                  s=s.substring(0,l-1);
                  fieldname=s;
                  state=FIELDDATA;
                }
                else
                {                           //将文件名解析出来
                  String temp=s;
                  pos=s.indexOf("filename=");
                  pos+="filename=".length()+1;
                  s=s.substring(pos);
                  int l=s.length();
                  s=s.substring(0,l-1);
                  pos=s.lastIndexOf("\\");
                  s=s.substring(pos+1);
                  filename=s;
                                           //从字节数组中取出文件数组
                  pos=byteIndexOf(b,temp,0);
                  b=subBytes(b,pos+temp.getBytes().length+2,b.length);//去掉前面的部分
                  s=reqbuf.readLine();
                  b=subBytes(b,s.getBytes().length+4,b.length);
                  pos=byteIndexOf(b,boundary,0);
                  b=subBytes(b,0,pos-1);
                  File f=new File(formfields.get("FilePath")+"\\"+filename);  //写入文件
                  DataOutputStream fileout=new DataOutputStream(new FileOutputStream(f));
                  fileout.write(b,0,b.length-1);
                  filesize=b.length-1;
                  state=FILEDATA;
                }
                break;
             case FIELDDATA:
                s=reqbuf.readLine();
                fieldvalue=s;
                formfields.put(fieldname,fieldvalue);
                state=NONE;
                break;
             case FILEDATA:
                while((!s.startsWith(boundary))&&(!s.startsWith(lastboundary)))
                {
                   s=reqbuf.readLine();
                   if (s.startsWith(boundary))
                   {
                      state=DATAHEADER;
                      break;
                   }
                }
                break;
          }
        }
        //指定输出类型
        response.setContentType("text/html;charset=gb2312");
        PrintWriter out =response.getWriter();
        out.println("<html>");
        out.println("<head><title>文件上传结果</title></head>");
        out.println("<body>");
        out.println("<h1>文件上传结果</h1><hr>");
        out.println("ID为"+formfields.get("FileID")+"的文件"+filename+"已经上传!"+
                    "文件长度为:"+filesize+"字节");
        out.println("</body></html>");
        out.close();
       
    }
   
     //Get Servlet information
      public String getServletInfo() {
        return "UploadServlet.UploadServlet Information";
      }
     
      //字节数组中的INDEXOF函数,与STRING类中的INDEXOF类似
      private static int byteIndexOf(byte[] b,String s,int start)
      {
          return byteIndexOf(b,s.getBytes(),start);
      }
     
      //字节数组中的INDEXOF函数,与STRING类中的INDEXOF类似
      private static int byteIndexOf(byte[] b,byte[] s,int start)
      {
         int i;
         if(s.length==0)
         {
           return 0;
         }
         int max=b.length-s.length;
         if(max<0)
            return -1;
         if(start>max)
            return -1;
         if (start<0)
            start=0;
        search:
         for(i=start;i<=max;i++)
         {
            if (b[i]==s[0])
            {
               int k=1;
               while(k<s.length)
               {
                 if(b[k+i]!=s[k])
                 {
                    continue search;
                 }
                 k++;
               }
               return i;
            }
         }
         return -1;
     }
     
     //用于从一个字节数组中提取一个字节数组
     private static byte[] subBytes(byte[] b,int from,int end)
     {
        byte[] result=new byte[end-from];
        System.arraycopy(b,from,result,0,end-from);
        return result;
     }
     
     //用于从一个字节数组中提取一个字符串
     private static String subBytesString(byte[] b,int from,int end)
     {
       return new String(subBytes(b,from,end));
     }

}
2:客户端的代码 index.html

 

<html>
 
<head>
<meta http-equiv="Content-Language" content="zh-cn">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>上传文件</title>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse"
  bordercolor="#111111" width="100%" id="AutoNumber1">
  <tr>
    <td width="15%"> </td>
    <td width="80%">
    <table border="0" cellpadding="10" cellspacing="10" style="border-collapse: collapse"
       bordercolor="#111111" width="100%" id="AutoNumber5">
      <tr>
        <td width="100%"><b><font face="黑体">全文辅助工具之一:上传文件接收</font></b></td>
      </tr>
      <tr>
        <td width="100%">
        <p align="right"><font color="#FF0000" size="2">作者:qixiaorui</font></td>
      </tr>
    </table>
    </td>
    <td width="5%"> </td>
  </tr>
  <tr>
    <td width="15%"> </td>
    <td width="80%">
    <table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111"
        width="100%" id="AutoNumber2">
      <tr>
        <td width="100%">
        <form method="POST" enctype="multipart/form-data" action="http://localhost:8080/UpAndDownTest/upload">
          <table border="0" cellpadding="10" cellspacing="10" style="border-collapse: collapse"
                        bordercolor="#111111" width="100%" id="AutoNumber3">
            <tr>
              <td width="100%" bgcolor="#00FFFF">
              <p align="center"><font face="华文仿宋" color="#000080"><b>
              --------------------------------- 上 传 文 件
              ----------------------------------</b></font></td>
            </tr>
            <tr>
              <td width="100%">
              <table border="0" cellpadding="3" cellspacing="3" style="border-collapse: collapse"
                            bordercolor="#111111" width="100%" id="AutoNumber4">
                <tr>
                  <td width="27%">请输入服务器路径:</td>
                  <td width="73%"><input type="text" name="FilePath" size="52">  
                  如: c:\aa</td>
                </tr>
                <tr>
                  <td width="27%">请输入操作ID:</td>
                  <td width="73%"><input type="text" name="FileID" size="52"></td>
                </tr>
                <tr>
                  <td width="27%">请输入文件路径:</td>
                  <td width="73%"><input type="file" name="FileData" size="41"></td>
                </tr>
              </table>
              </td>
            </tr>
            <tr>
              <td width="100%">
              <input type="submit" value="提交" name="uploadfile">  
              <input type="reset" value="重置" name="B2"></td>
            </tr>
          </table>
        </form>
        </td>
      </tr>
    </table>
    </td>
    <td width="5%"> </td>
  </tr>
  <tr>
    <td width="15%"> </td>
    <td width="80%"> </td>
    <td width="5%"> </td>
  </tr>
</table>
</body>
</html>

3:配置端代码:web.xml

<?xml version="1.0" encoding="iso-8859-1"?>
   <web-app id="IDOLSearch">
        <display-name>test</display-name>
        <description>This is Idol Sever Default Web Application.</description>
        <servlet>
<servlet-name>UploadServlet</servlet-name>
    <servlet-class>com.test.action.ServletAction</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>UploadServlet</servlet-name>
    <url-pattern>/upload/*</url-pattern>
</servlet-mapping>
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
        </welcome-file-list>             
    </web-app>

=============================================================

对于web应用的一些下载可以用一些现成的插件,例如common-fileupload组件
下载地址:http://jakarta.apache.org/commons /fileupload/import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;

public class Upload extends HttpServlet {

    private String uploadPath = "C:\\upload\\"; // 用于存放上传文件的目录
    private String tempPath = "C:\\upload\\tmp\\"; // 用于存放临时文件的目录

public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
{
    try {
        DiskFileUpload fu = new DiskFileUpload();
        // 设置最大文件尺寸,这里是4MB
        fu.setSizeMax(4194304);
        // 设置缓冲区大小,这里是4kb
        fu.setSizeThreshold(4096);
        // 设置临时目录:
        fu.setRepositoryPath(tempPath);

        // 得到所有的文件:
        List fileItems = fu.parseRequest(request);
        Iterator i = fileItems.iterator();
        // 依次处理每一个文件:
        while(i.hasNext()) {
            FileItem fi = (FileItem)i.next();
            // 获得文件名,这个文件名包括路径:
            String fileName = fi.getName();
            if(fileName!=null) {
                // 在这里可以记录用户和文件信息
                // ...
                // 写入文件a.txt,你也可以从fileName中提取文件名:
                fi.write(new File(uploadPath + "a.txt"));
            }
        }
        // 跳转到上传成功提示页面
    }
    catch(Exception e) {
        // 可以跳转出错页面
    }
}
}

//当servlet收到浏览器发出的Post请求后,在doPost()方法中实现文件上传。以下是示例代码:


如果要在配置文件中读取指定的上传文件夹,可以在init()方法中执行:

public void init() throws ServletException {
    uploadPath = ....
    tempPath = ....
    // 文件夹不存在就自动创建:
    if(!new File(uploadPath).isDirectory())
        new File(uploadPath).mkdirs();
    if(!new File(tempPath).isDirectory())
        new File(tempPath).mkdirs();
}

配置servlet,用记事本打开tomcat\webapps\你的webapp\WEB-INF\web.xml,没有的话新建一个。典型配置如下:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <servlet>
        <servlet-name>Upload</servlet-name>
        <servlet-class>Upload</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Upload</servlet-name>
        <url-pattern>/fileupload</url-pattern>
    </servlet-mapping>
</web-app>

配置好servlet后,启动tomcat,写一个简单的html测试:

<form action="fileupload" method="post" enctype="multipart/form-data" name="form1">
  <input type="file" name="file">
  <input type="submit" name="Submit" value="upload">
</form>

注意action="fileupload"其中fileupload是配置servlet时指定的url-pattern。

================================================================

还有如:commons-fileupload-1.2.1.jar

try {
DiskFileItemFactory dfif=new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(dfif);
upload.setSizeMax(10*1024*1024);
List list=upload.parseRequest(request);
for(int i=0;i<list.size();i++){
FileItem item=(FileItem) list.get(i);
String name=item.getName();
String path=this.getServletContext().getRealPath("/upload");
item.write(new File(path,name));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

 

 

你可能感兴趣的:(java,tomcat,Web,servlet,网络应用)