常用的上传下载协议以及Java实现

作者: ldsea 分类: 程序生活 发布时间: 2011-04-17 13:48

上传协议

1.HTTP协议

HTTP协议即Hypertext Transfer Protocol的缩写,这种协议是网上最常见的传输协议。

1.1 用Java实现通过HTTP协议来上传文件

方式一:使用Apache 开源上传软件包 fileupload,相关介绍及下载地址是http://commons.apache.org/fileupload/

核心示例代码:

File uploadPath = new File("D:\\temp");//上传文件目录
    if (!uploadPath.exists()) {
       uploadPath.mkdirs();
    }
    // 临时文件目录
    File tempPathFile = new File("d:\\temp\\buffer\\");
    if (!tempPathFile.exists()) {
       tempPathFile.mkdirs();
    }
    try {
       // Create a factory for disk-based file items
       DiskFileItemFactory factory = new DiskFileItemFactory();

       // Set factory constraints
       factory.setSizeThreshold(4096); // 设置缓冲区大小,这里是4kb
       factory.setRepository(tempPathFile);//设置缓冲区目录

       // Create a new file upload handler
       ServletFileUpload upload = new ServletFileUpload(factory);

       // Set overall request size constraint
       upload.setSizeMax(4194304); // 设置最大文件尺寸,这里是4MB

       List<FileItem> items = upload.parseRequest(request);//得到所有的文件
       Iterator<FileItem> i = items.iterator();
       while (i.hasNext()) {
           FileItem fi = (FileItem) i.next();
           String fileName = fi.getName();
           if (fileName != null) {
       File fullFile = new File(fi.getName());
       File savedFile = new File(uploadPath, fullFile
              .getName());
       fi.write(savedFile);
           }
       }
       out.print("upload succeed");
    } catch (Exception e) {
       e.printStackTrace();
    }

方式二:使用jspSmartUpload组件

核心示例代码:

/新建一个SmartUpload对象  
    SmartUpload su = new SmartUpload();  
 
    //上传初始化  
    su.initialize(pageContext);  
 
    // 设定上传限制  
    //1.限制每个上传文件的最大长度。  
    su.setMaxFileSize(10000000);  
 
    //2.限制总上传数据的长度。  
    su.setTotalMaxFileSize(20000000);  
 
    //3.设定允许上传的文件(通过扩展名限制) 
    su.setAllowedFilesList("doc,txt,jpg,rar,mid,waw,mp3,gif");  
      
    boolean sign = true;  
      
    //4.设定禁止上传的文件(通过扩展名限制),禁止上传带有exe,bat,jsp,htm,html扩展名的文件和没有扩展名的文件。  
    try {  
        su.setDeniedFilesList("exe,bat,jsp,htm,html");  
 
        //上传文件  
        su.upload();  
        //将上传文件保存到指定目录  
        su.save("c:\\"); 

    } catch (Exception e) { 
        e.printStackTrace(); 
        sign = false
    } 
    if(sign==true
    { 
        out.println("<script>parent.callback('upload file success')</script>"); 
    }else 
    { 
        out.println("<script>parent.callback('upload file error')</script>");  
    }

方式三:Struts1实现文件上传

public ActionForward upLoadFile(ActionMapping mapping, ActionForm form,
                                    HttpServletRequest request,
                                    HttpServletResponse response) throws
            Exception {
    ActionForward forward=null;
        Date date = new Date();
        FileActionForm fileActionForm = (FileActionForm) form;
        //FormFile用于指定存取文件的类型
        FormFile file = fileActionForm.getFile(); //获取当前的文件
      // 获得系统的绝对路径 String dir = servlet.getServletContext().getRealPath("/image");
        //我上传的文件没有放在服务器上。而是存在D:D:\\loadfile\\temp\\
        String dir="D:\\loadfile\\temp\\";
        int i = 0;
   String type = file.getFileName();
   while(i!=-1){
   //找到上传文件的类型的位置,这个地方的是'.'
    i = type.indexOf(".");
   /* System.out.println(i);*/
    /*截取上传文件的后缀名,此时得到了文件的类型*/
    type = type.substring(i+1);
   }
// 限制上传类型为jpg,txt,rar;
   if (!type.equals("jpg") && !type.equals("txt")&& !type.equals("bmp"))
  
  {//当上传的类型不为上述类型时,跳转到错误页面。
    forward=mapping.findForward("error");
   }
   else
   { 
//    将上传时间加入文件名(这个地方的是毫秒数)  
     String times = String.valueOf(date.getTime());
   //组合成 time.type
         String fname = times + "." + type;
       //InInputStream是用以从特定的资源读取字节的方法。
          InputStream streamIn = file.getInputStream();    //创建读取用户上传文件的对象
          //得到是字节数,即byte,我们可以直接用file.getFileSize(),也可以在创建读取对象时用streamIn.available();
         // int ok=streamIn.available();          
          int ok=file.getFileSize();
          String strFee = null;
         //这个地方是处理上传的为M单位计算时,下一个是以kb,在下一个是byte;
         
          if(ok>=1024*1024)
          {
          float ok1=(((float)ok)/1024f/1024f);
           DecimalFormat myformat1 = new DecimalFormat("0.00");        
          strFee = myformat1.format(ok1)+"M";
                 System.out.println(strFee+"M");
          }
          else if(ok>1024 && ok<=1024*1024)
          {
             double ok2=((double)ok)/1024;
             DecimalFormat myformat2=new DecimalFormat("0.00");
            strFee = myformat2.format(ok2)+"kb";
                 System.out.println(strFee+"kb");
          }
          else if(ok<1024)
          {
          System.out.println("aaaaaaaaa");
           strFee=String.valueOf(ok)+"byte";
           System.out.println(strFee);
          
          }
          System.out.println( streamIn.available()+"文件大小byte");
          //这个是io包下的上传文件类
          File uploadFile = new File(dir);   //指定上传文件的位置
          if (!uploadFile.exists() || uploadFile == null) { //判断指定路径dir是否存在,不存在则创建路径
              uploadFile.mkdirs();
          }
          //上传的路径+文件名
          String path = uploadFile.getPath() + "\\" + fname;
       //OutputStream用于向某个目标写入字节的抽象类,这个地方写入目标是path,通过输出流FileOutputStream去写
          OutputStream streamOut = new FileOutputStream(path);
          int bytesRead = 0;
          byte[] buffer = new byte[8192];
          //将数据读入byte数组的一部分,其中读入字节数的最大值是8192,读入的字节将存储到,buffer[0]到buffer[0+8190-1]的部分中
          //streamIn.read方法返回的是实际读取字节数目.如果读到末尾则返回-1.如果bytesRead返回为0则表示没有读取任何字节。
          while ((bytesRead = streamIn.read(buffer, 0, 8192)) != 1) {
          //写入buffer数组的一部分,从buf[0]开始写入并写入bytesRead个字节,这个write方法将发生阻塞直至字节写入完成。
              streamOut.write(buffer, 0, bytesRead);
          }
        // 关闭输出输入流,销毁File流。
          streamOut.close();
          streamIn.close();
          file.destroy();   
          String paths=path;
          System.out.println(paths);
         String fileName = Chinese.toChinese(fileActionForm.getFileName()); //获取文件的名称
        //String fileSize = String.valueOf(file.getFileSize());
         String fileDate = DateFormat.getDateInstance().format(date);
         String sql = "insert into tb_file values('" + fileName + "','" +
         strFee + "','" + fileDate + "','" + paths + "')";
         connection.executeUpdate(sql);
         connection.closeConnection();
         forward=mapping.findForward("upLoadFileResult");
   }

方式四:Struts2实现文件上传

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class FileUploadAction extends ActionSupport {
    private static final long serialVersionUID = 572146812454l ;
    private static final int BUFFER_SIZE = 16 * 1024 ;
  
    private File myFile;
    private String contentType;
    private String fileName;
    private String imageFileName;
    private String caption;
  
    public void setMyFileContentType(String contentType) {
        this .contentType = contentType;
   }
  
    public void setMyFileFileName(String fileName) {
        this .fileName = fileName;
   }
      
    public void setMyFile(File myFile) {
        this .myFile = myFile;
   }
  
    public String getImageFileName() {
        return imageFileName;
   }
  
    public String getCaption() {
        return caption;
   }

    public void setCaption(String caption) {
        this .caption = caption;
   }
  
    private static void copy(File src, File dst) {
        try {
           InputStream in = null ;
           OutputStream out = null ;
            try {               
               in = new BufferedInputStream( new FileInputStream(src), BUFFER_SIZE);
               out = new BufferedOutputStream( new FileOutputStream(dst), BUFFER_SIZE);
                byte [] buffer = new byte [BUFFER_SIZE];
                while (in.read(buffer) > 0 ) {
                   out.write(buffer);
               }
           } finally {
                if ( null != in) {
                   in.close();
               }
                if ( null != out) {
                   out.close();
               }
           }
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
  
    private static String getExtention(String fileName) {
        int pos = fileName.lastIndexOf( " . " );
        return fileName.substring(pos);
   }

   @Override
    public String execute()     {       
       imageFileName = new Date().getTime() + getExtention(fileName);
       File imageFile = new File(ServletActionContext.getServletContext().getRealPath( " /UploadImages " ) + " / " + imageFileName);
       copy(myFile, imageFile);
        return SUCCESS;
   }
  
}

方式五:通过HttpClient组件实现上传

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

上传部分示例代码:

import java.io.File
import java.io.IOException
 
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.HttpStatus
import org.apache.http.client.ClientProtocolException
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.mime.MultipartEntity
import org.apache.http.entity.mime.content.FileBody
import org.apache.http.entity.mime.content.StringBody
import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.util.EntityUtils
 
public class SendFile { 
 
    public static void main(String[] args) throws ClientProtocolException, 
            IOException { 
        HttpClient httpclient = new DefaultHttpClient(); 
        //请求处理页面 
        HttpPost httppost = new HttpPost
                "http://localhost:8080/webtools/upload.jsp"); 
        //创建待处理的文件 
        FileBody file = new FileBody(new File("d:/22.rar")); 
        //创建待处理的表单域内容文本 
        StringBody descript = new StringBody("0431.la"); 
 
        //对请求的表单域进行填充 
        MultipartEntity reqEntity = new MultipartEntity(); 
        reqEntity.addPart("file", file); 
        reqEntity.addPart("descript", descript); 
        //设置请求 
        httppost.setEntity(reqEntity); 
        //执行 
        HttpResponse response = httpclient.execute(httppost); 
        //HttpEntity resEntity = response.getEntity(); 
        //System.out.println(response.getStatusLine()); 
        if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){ 
            HttpEntity entity = response.getEntity(); 
            //显示内容 
            if (entity != null) { 
                System.out.println(EntityUtils.toString(entity)); 
            } 
            if (entity != null) { 
                entity.consumeContent(); 
            } 
        } 
    } 
}

2.FTP协议

FTP协议即File Transfer Protocol的缩写,这种协议通常可以匿名登陆到某个FTP服务器上进行文件传
输。

2.1利用jakarta commons中的FTPClient(在commons-net包中)实现上传文件。

网站是http://commons.apache.org/net

示例代码:

/**
     * Description: 向FTP服务器上传文件
     * @param url FTP服务器hostname
     * @param port FTP服务器端口
     * @param username FTP登录账号
     * @param password FTP登录密码
     * @param path FTP服务器保存目录
     * @param filename 上传到FTP服务器上的文件名
     * @param input 输入流
     * @return 成功返回true,否则返回false
     */
    public static boolean uploadFile(String url,int port,String username, String password, String path, String filename, InputStream input) {
        boolean success = false;
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(url, port);//连接FTP服务器
            //如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
            ftp.login(username, password);//登录
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return success;
            }
            ftp.changeWorkingDirectory(path);
            ftp.storeFile(filename, input);           
           
            input.close();
            ftp.logout();
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }

2.2使用SUN公司的FtpClient

/**
   * upload
   * 上传文件
   * @throws java.lang.Exception
   * @return -1 文件不存在
   *          -2 文件内容为空
   *          >0 成功上传,返回文件的大小
   * @param newname 上传后的新文件名
   * @param filename 上传的文件
   */
public long upload(String filename,String newname) throws Exception
{
    long result = 0;
    TelnetOutputStream os = null;
    FileInputStream is = null;
    try {        
        java.io.File file_in = new java.io.File(filename);
        if (!file_in.exists()) return 1;
        if (file_in.length()==0) return 2;
        os = ftpClient.put(newname);
        result = file_in.length();
        is = new FileInputStream(file_in);
        byte[] bytes = new byte[1024];
        int c;
        while ((c = is.read(bytes)) != 1) {
             os.write(bytes, 0, c);
        }
    } finally {
        if (is != null) {
            is.close();
        }
        if (os != null) {
           os.close();
        }
    }
   return result;
}
/**
   * upload
   * @throws java.lang.Exception
   * @return
   * @param filename
   */
public long upload(String filename)
throws Exception
{
   String newname = "";
   if (filename.indexOf("/")>-1)
   {
      newname = filename.substring(filename.lastIndexOf("/")+1);
   }else
   {
      newname = filename;
   }
   return upload(filename,newname);
}

3.基于P2P的协议

基于Java的P2P协议实现方式之一为JXTA

JXTA(发音作“juxta”)是Sun微系统对等网络(P2P)的标准,这是一个努力的方向,以它来促进和探究分布式计算的新方法。“JXTA”这个 名字既用来指代这个标准,也用来指代研究出来的技术,这种技术处于传输平台和P2P通信协议的环绕之中。其开发组织被取名为单词“juxtapose(并 置)”的简易形式。

Jxta目前定义了6个协议,但并不是要求Jxta peer实现全部的6个协议。Peer实现协议的数量取决于这个peer的能力;一个peer甚至可以只实现一个协议。Peer也能够根据自身的需求扩展任意一个协议。

值 得注意的一点是Jxta协议本身并不保证互操作性。Jxta和TCP/IP在应用的时候是类同的。正如虽然FTP和HTTP都是建立在TCP/IP基础之 上的,但你不能用FTP客户端去访问网页。在Jxta中也一样,假如有两种应用都是建立在Jxta之上的,并不说明它们之间一定能够具有互操作性。互操作 性有开发者自己设计实现。尽管如此,开发者将应用建立在Jxt提供的护操作层之上,这样就减少了对于护操作性的实现困难。

关于JXTA协议的更多知识可参考:http://www.javaworld.com/javaworld/jw-10-2001/jw-1019-jxta-p2.html

下载协议:

1.HTTP协议

方式一:使用文件输入流下载

String aFilePath = null;     //要下载的文件路径
          String aFileName = null;     //要下载的文件名
          FileInputStream in = null;   //输入流
          ServletOutputStream out = null;   //输出流

          try
    {
         
              aFilePath = getFilePath(request);
              aFileName = getFileName(request);

              response.setContentType(getContentType(aFileName) + "; charset=UTF-8");
              response.setHeader("Content-disposition", "attachment; filename=" + aFileName);

              in = new   FileInputStream(aFilePath + aFileName); //读入文件
             out = response.getOutputStream();
             out.flush();
             int aRead = 0;
            while((aRead = in.read()) != 1 & in != null)
         {
              out.write(aRead);
          }
            out.flush();
       }
        catch(Throwable e)
      {
      log.error("FileDownload doGet() IO error!",e);
       }
          finally
          {
              try
              {
                  in.close();
                  out.close();
              }
              catch(Throwable e)
              {
               log.error("FileDownload doGet() IO close error!",e);
              }
          }

方式二:Struts1实现文件下载

public ActionForward downFile(ActionMapping mapping, ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response) throws
           Exception {
       String path = request.getParameter("path");
       System.out.println(path+"111");
       BufferedInputStream bis = null;
       BufferedOutputStream bos = null;
       OutputStream fos = null;
       InputStream fis = null;
      
     //如果是从服务器上取就用这个获得系统的绝对路径方法。 String filepath = servlet.getServletContext().getRealPath("/" + path);
       String filepath=path;
       System.out.println("文件路径"+filepath);
       File uploadFile = new File(filepath);
       fis = new FileInputStream(uploadFile);
       bis = new BufferedInputStream(fis);
       fos = response.getOutputStream();
       bos = new BufferedOutputStream(fos);
       //这个就就是弹出下载对话框的关键代码
       response.setHeader("Content-disposition",
                          "attachment;filename=" +
                          URLEncoder.encode(path, "utf-8"));
       int bytesRead = 0;
       //这个地方的同上传的一样。我就不多说了,都是用输入流进行先读,然后用输出流去写,唯一不同的是我用的是缓冲输入输出流
       byte[] buffer = new byte[8192];
       while ((bytesRead = bis.read(buffer, 0, 8192)) != 1) {
           bos.write(buffer, 0, bytesRead);
       }
       bos.flush();
       fis.close();
       bis.close();
       fos.close();
       bos.close();
       return null;
   }

方式三:Struts2实现文件下载

public class FileDownloadAction implements Action{  
   //该属性值在配置文件中指定,Struts2会自动进行注入(即赋值),需要为该属性提供setter和 getter方法  
   private String inputPath;//指定要下载的文件的完整路径(路径名+文件名)  
   /* 
     * 实现下载的Action类应该提供一个返回InputStream实例的方法,该方法对应在       
        <result…/>里的inputName属性值为targetFile 
   */ 
   public InputStream getTargetFile() throws Exception{  
      return  ServletActionContext.getServletContext().getResourceAsStream(inputPath);  
   }  
   //处理用户请求的execute方法,该方法返回success字符串  
   public String execute() throws Exception{  
      return "success";  
   }  
}

方式四:通过HttpClient组件实现下载文件

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

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

public class SearchDomain {

    public static void main(String[] args) throws ClientProtocolException, IOException {
        //实例化一个HttpClient
        HttpClient httpClient = new DefaultHttpClient();
        //设定目标站点  web的默认端口80可以不写的 当然如果是其它端口就要标明                                                          
        HttpHost httpHost = new HttpHost("www.shanhe114.com",80);
        //设置需要下载的文件
        HttpGet httpGet = new HttpGet("/test.zip");
        //这里也可以直接使用httpGet的绝对地址,当然如果不是具体地址不要忘记/结尾
        //HttpGet httpGet = new HttpGet("http://www.0431.la/");
        //HttpResponse response = httpClient.execute(httpGet);
       
        HttpResponse response = httpClient.execute(httpHost, httpGet);
        if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){
            //请求成功
            //取得请求内容
            HttpEntity entity = response.getEntity();
           
            //显示内容
            if (entity != null) {
                //这里可以得到文件的类型 如image/jpg /zip /tiff 等等 但是发现并不是十分有效,有时明明后缀是.rar但是取到的是null,这点特别说明
                System.out.println(entity.getContentType());
                //可以判断是否是文件数据流
                System.out.println(entity.isStreaming());
                //设置本地保存的文件
                File storeFile = new File("c:/0431la.zip"); 
                FileOutputStream output = new FileOutputStream(storeFile);
                //得到网络资源并写入文件
                InputStream input = entity.getContent();
                byte b[] = new byte[1024];
                int j = 0;
                while( (j = input.read(b))!=-1){
                    output.write(b,0,j);
                }
                output.flush();
                output.close();
            }
            if (entity != null) {
                entity.consumeContent();
            }
        }
    }
}

2.FTP协议

利用jakarta commons中的FTPClient(在commons-net包中)实现上传文件。

网站是http://commons.apache.org/net

示例代码:

/**
     * Description: 从FTP服务器下载文件
     * @Version1.0 Jul 27, 2008 5:32:36 PM by 崔红保(cuihongbao@d-heaven.com)创建
     * @param url FTP服务器hostname
     * @param port FTP服务器端口
     * @param username FTP登录账号
     * @param password FTP登录密码
     * @param remotePath FTP服务器上的相对路径
     * @param fileName 要下载的文件名
     * @param localPath 下载后保存到本地的路径
     * @return
     */
    public static boolean downFile(String url, int port,String username, String password, String remotePath,String fileName,String localPath) {
        boolean success = false;
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(url, port);
            //如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
            ftp.login(username, password);//登录
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return success;
            }
            ftp.changeWorkingDirectory(remotePath);//转移到FTP服务器目录
            FTPFile[] fs = ftp.listFiles();
            for(FTPFile ff:fs){
                if(ff.getName().equals(fileName)){
                    File localFile = new File(localPath+"/"+ff.getName());
                   
                    OutputStream is = new FileOutputStream(localFile);
                    ftp.retrieveFile(ff.getName(), is);
                    is.close();
                }
            }
           
            ftp.logout();
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }

 

2.2使用SUN公司的FTPClient包

 

 

/**
    *  download
    *  从ftp下载文件到本地
    * @throws java.lang.Exception
    * @return
    * @param newfilename 本地生成的文件名
    * @param filename 服务器上的文件名
    */
public long download(String filename,String newfilename)
throws Exception
{ 
    long result = 0;
    TelnetInputStream is = null;
    FileOutputStream os = null;
    try
    {
       is = ftpClient.get(filename);      
       java.io.File outfile = new java.io.File(newfilename);
       os = new FileOutputStream(outfile);
       byte[] bytes = new byte[1024];
       int c;
       while ((c = is.read(bytes)) != 1) {
           os.write(bytes, 0, c);
           result = result + c;
       }
    } catch (IOException e)
    {
       e.printStackTrace();
    }
    finally {
         if (is != null) {
             is.close();
         }
         if (os != null) {
            os.close();
         }
     }
     return result;
}

 

3.基于P2P的协议

见上传协议中介绍的JXTA

发表回复

您的电子邮箱地址不会被公开。