欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android基于Http协议实现文件上传功能的方法

程序员文章站 2024-03-03 21:13:58
本文实例讲述了android基于http协议实现文件上传功能的方法。分享给大家供大家参考,具体如下: 注意一般使用http协议上传的文件都比较小,一般是小于2m 这里示...

本文实例讲述了android基于http协议实现文件上传功能的方法。分享给大家供大家参考,具体如下:

注意一般使用http协议上传的文件都比较小,一般是小于2m

这里示例是上传一个小的mp3文件

1.主activity:mainactivity.java

public class mainactivity extends activity
{
  private static final string tag = "mainactivity";
  private edittext timelengthtext;
  private edittext titletext;
  private edittext videotext;
  @override
  public void oncreate(bundle savedinstancestate)
  {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.main);
    //提交上传按钮
    button button = (button) this.findviewbyid(r.id.button);
    timelengthtext = (edittext) this.findviewbyid(r.id.timelength);
    videotext = (edittext) this.findviewbyid(r.id.video);
    titletext = (edittext) this.findviewbyid(r.id.title);
    button.setonclicklistener(new view.onclicklistener()
    {
      @override
      public void onclick(view v)
      {
        string title = titletext.gettext().tostring();
        string timelength = timelengthtext.gettext().tostring();
        map<string, string> params = new hashmap<string, string>();
        params.put("method", "save");
        params.put("title", title);
        params.put("timelength", timelength);
        try
        {
          //得到sdcard的目录
          file uploadfile = new file(environment.getexternalstoragedirectory(), videotext.gettext().tostring());
          //上传音频文件
          formfile formfile = new formfile("02.mp3", uploadfile, "video", "audio/mpeg");
          sockethttprequester.post("http://192.168.1.100:8080/videoweb/video/manage.do", params, formfile);
          toast.maketext(mainactivity.this, r.string.success, 1).show();
        }
        catch (exception e)
        {
          toast.maketext(mainactivity.this, r.string.error, 1).show();
          log.e(tag, e.tostring());
        }
      }
    });
  }
}

2.上传工具类,注意里面构造协议字符串需要根据不同的提交表单来处理

public class sockethttprequester
{
  /**
   * 发送xml数据
   * @param path 请求地址
   * @param xml xml数据
   * @param encoding 编码
   * @return
   * @throws exception
   */
  public static byte[] postxml(string path, string xml, string encoding) throws exception{
    byte[] data = xml.getbytes(encoding);
    url url = new url(path);
    httpurlconnection conn = (httpurlconnection)url.openconnection();
    conn.setrequestmethod("post");
    conn.setdooutput(true);
    conn.setrequestproperty("content-type", "text/xml; charset="+ encoding);
    conn.setrequestproperty("content-length", string.valueof(data.length));
    conn.setconnecttimeout(5 * 1000);
    outputstream outstream = conn.getoutputstream();
    outstream.write(data);
    outstream.flush();
    outstream.close();
    if(conn.getresponsecode()==200){
      return readstream(conn.getinputstream());
    }
    return null;
  }
  /**
   * 直接通过http协议提交数据到服务器,实现如下面表单提交功能:
   *  <form method=post action="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">
      <input type="text" name="name">
      <input type="text" name="id">
      <input type="file" name="imagefile"/>
      <input type="file" name="zip"/>
     </form>
   * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
   *         因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
   * @param params 请求参数 key为参数名,value为参数值
   * @param file 上传文件
   */
  public static boolean post(string path, map<string, string> params, formfile[] files) throws exception
  {
    //数据分隔线
    final string boundary = "---------------------------7da2137580612";
    //数据结束标志"---------------------------7da2137580612--"
    final string endline = "--" + boundary + "--/r/n";
    //下面两个for循环都是为了得到数据长度参数,依据表单的类型而定
    //首先得到文件类型数据的总长度(包括文件分割线)
    int filedatalength = 0;
    for(formfile uploadfile : files)
    {
      stringbuilder fileexplain = new stringbuilder();
      fileexplain.append("--");
      fileexplain.append(boundary);
      fileexplain.append("/r/n");
      fileexplain.append("content-disposition: form-data;name=/""+ uploadfile.getparametername()+"/";filename=/""+ uploadfile.getfilname() + "/"/r/n");
      fileexplain.append("content-type: "+ uploadfile.getcontenttype()+"/r/n/r/n");
      fileexplain.append("/r/n");
      filedatalength += fileexplain.length();
      if(uploadfile.getinstream()!=null){
        filedatalength += uploadfile.getfile().length();
      }else{
        filedatalength += uploadfile.getdata().length;
      }
    }
    //再构造文本类型参数的实体数据
    stringbuilder textentity = new stringbuilder();
    for (map.entry<string, string> entry : params.entryset())
    {
      textentity.append("--");
      textentity.append(boundary);
      textentity.append("/r/n");
      textentity.append("content-disposition: form-data; name=/""+ entry.getkey() + "/"/r/n/r/n");
      textentity.append(entry.getvalue());
      textentity.append("/r/n");
    }
    //计算传输给服务器的实体数据总长度(文本总长度+数据总长度+分隔符)
    int datalength = textentity.tostring().getbytes().length + filedatalength + endline.getbytes().length;
    url url = new url(path);
    //默认端口号其实可以不写
    int port = url.getport()==-1 ? 80 : url.getport();
    //建立一个socket链接
    socket socket = new socket(inetaddress.getbyname(url.gethost()), port);
    //获得一个输出流(从android流到web)
    outputstream outstream = socket.getoutputstream();
    //下面完成http请求头的发送
    string requestmethod = "post "+ url.getpath()+" http/1.1/r/n";
    outstream.write(requestmethod.getbytes());
    //构建accept
    string accept = "accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*/r/n";
    outstream.write(accept.getbytes());
    //构建language
    string language = "accept-language: zh-cn/r/n";
    outstream.write(language.getbytes());
    //构建contenttype
    string contenttype = "content-type: multipart/form-data; boundary="+ boundary+ "/r/n";
    outstream.write(contenttype.getbytes());
    //构建contentlength
    string contentlength = "content-length: "+ datalength + "/r/n";
    outstream.write(contentlength.getbytes());
    //构建alive
    string alive = "connection: keep-alive/r/n";
    outstream.write(alive.getbytes());
    //构建host
    string host = "host: "+ url.gethost() +":"+ port +"/r/n";
    outstream.write(host.getbytes());
    //写完http请求头后根据http协议再写一个回车换行
    outstream.write("/r/n".getbytes());
    //把所有文本类型的实体数据发送出来
    outstream.write(textentity.tostring().getbytes());
    //把所有文件类型的实体数据发送出来
    for(formfile uploadfile : files)
    {
      stringbuilder fileentity = new stringbuilder();
      fileentity.append("--");
      fileentity.append(boundary);
      fileentity.append("/r/n");
      fileentity.append("content-disposition: form-data;name=/""+ uploadfile.getparametername()+"/";filename=/""+ uploadfile.getfilname() + "/"/r/n");
      fileentity.append("content-type: "+ uploadfile.getcontenttype()+"/r/n/r/n");
      outstream.write(fileentity.tostring().getbytes());
      //边读边写
      if(uploadfile.getinstream()!=null)
      {
        byte[] buffer = new byte[1024];
        int len = 0;
        while((len = uploadfile.getinstream().read(buffer, 0, 1024))!=-1)
        {
          outstream.write(buffer, 0, len);
        }
        uploadfile.getinstream().close();
      }
      else
      {
        outstream.write(uploadfile.getdata(), 0, uploadfile.getdata().length);
      }
      outstream.write("/r/n".getbytes());
    }
    //下面发送数据结束标志,表示数据已经结束
    outstream.write(endline.getbytes());
    bufferedreader reader = new bufferedreader(new inputstreamreader(socket.getinputstream()));
    //读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败
    if(reader.readline().indexof("200")==-1)
    {
      return false;
    }
    outstream.flush();
    outstream.close();
    reader.close();
    socket.close();
    return true;
  }
  /**
   * 提交数据到服务器
   * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
   * @param params 请求参数 key为参数名,value为参数值
   * @param file 上传文件
   */
  public static boolean post(string path, map<string, string> params, formfile file) throws exception
  {
    return post(path, params, new formfile[]{file});
  }
  /**
   * 提交数据到服务器
   * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
   * @param params 请求参数 key为参数名,value为参数值
   * @param encode 编码
   */
  public static byte[] postfromhttpclient(string path, map<string, string> params, string encode) throws exception
  {
    //用于存放请求参数
    list<namevaluepair> formparams = new arraylist<namevaluepair>();
    for(map.entry<string, string> entry : params.entryset())
    {
      formparams.add(new basicnamevaluepair(entry.getkey(), entry.getvalue()));
    }
    urlencodedformentity entity = new urlencodedformentity(formparams, encode);
    httppost httppost = new httppost(path);
    httppost.setentity(entity);
    //看作是浏览器
    httpclient httpclient = new defaulthttpclient();
    //发送post请求
    httpresponse response = httpclient.execute(httppost);
    return readstream(response.getentity().getcontent());
  }
  /**
   * 发送请求
   * @param path 请求路径
   * @param params 请求参数 key为参数名称 value为参数值
   * @param encode 请求参数的编码
   */
  public static byte[] post(string path, map<string, string> params, string encode) throws exception
  {
    //string params = "method=save&name="+ urlencoder.encode("老毕", "utf-8")+ "&age=28&";//需要发送的参数
    stringbuilder parambuilder = new stringbuilder("");
    if(params!=null && !params.isempty())
    {
      for(map.entry<string, string> entry : params.entryset())
      {
        parambuilder.append(entry.getkey()).append("=")
          .append(urlencoder.encode(entry.getvalue(), encode)).append("&");
      }
      parambuilder.deletecharat(parambuilder.length()-1);
    }
    byte[] data = parambuilder.tostring().getbytes();
    url url = new url(path);
    httpurlconnection conn = (httpurlconnection)url.openconnection();
    //设置允许对外发送请求参数
    conn.setdooutput(true);
    //设置不进行缓存
    conn.setusecaches(false);
    conn.setconnecttimeout(5 * 1000);
    conn.setrequestmethod("post");
    //下面设置http请求头
    conn.setrequestproperty("accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
    conn.setrequestproperty("accept-language", "zh-cn");
    conn.setrequestproperty("user-agent", "mozilla/4.0 (compatible; msie 8.0; windows nt 5.2; trident/4.0; .net clr 1.1.4322; .net clr 2.0.50727; .net clr 3.0.04506.30; .net clr 3.0.4506.2152; .net clr 3.5.30729)");
    conn.setrequestproperty("content-type", "application/x-www-form-urlencoded");
    conn.setrequestproperty("content-length", string.valueof(data.length));
    conn.setrequestproperty("connection", "keep-alive");
    //发送参数
    dataoutputstream outstream = new dataoutputstream(conn.getoutputstream());
    outstream.write(data);//把参数发送出去
    outstream.flush();
    outstream.close();
    if(conn.getresponsecode()==200)
    {
      return readstream(conn.getinputstream());
    }
    return null;
  }
  /**
   * 读取流
   * @param instream
   * @return 字节数组
   * @throws exception
   */
  public static byte[] readstream(inputstream instream) throws exception
  {
    bytearrayoutputstream outsteam = new bytearrayoutputstream();
    byte[] buffer = new byte[1024];
    int len = -1;
    while( (len=instream.read(buffer)) != -1)
    {
      outsteam.write(buffer, 0, len);
    }
    outsteam.close();
    instream.close();
    return outsteam.tobytearray();
  }
}
public class streamtool
{
  /**
   * 从输入流读取数据
   * @param instream
   * @return
   * @throws exception
   */
  public static byte[] readinputstream(inputstream instream) throws exception{
    bytearrayoutputstream outsteam = new bytearrayoutputstream();
    byte[] buffer = new byte[1024];
    int len = 0;
    while( (len = instream.read(buffer)) !=-1 ){
      outsteam.write(buffer, 0, len);
    }
    outsteam.close();
    instream.close();
    return outsteam.tobytearray();
  }
}
/**
 * 使用javabean封装上传文件数据
 *
 */
public class formfile
{
  //上传文件的数据
  private byte[] data;
  private inputstream instream;
  private file file;
  //文件名称
  private string filname;
  //请求参数名称
  private string parametername;
  //内容类型
  private string contenttype = "application/octet-stream";
  /**
   * 上传小文件,把文件数据先读入内存
   * @param filname
   * @param data
   * @param parametername
   * @param contenttype
   */
  public formfile(string filname, byte[] data, string parametername, string contenttype)
  {
    this.data = data;
    this.filname = filname;
    this.parametername = parametername;
    if(contenttype!=null) this.contenttype = contenttype;
  }
  /**
   * 上传大文件,一边读文件数据一边上传
   * @param filname
   * @param file
   * @param parametername
   * @param contenttype
   */
  public formfile(string filname, file file, string parametername, string contenttype)
  {
    this.filname = filname;
    this.parametername = parametername;
    this.file = file;
    try
    {
      this.instream = new fileinputstream(file);
    }
    catch (filenotfoundexception e)
    {
      e.printstacktrace();
    }
    if(contenttype!=null) this.contenttype = contenttype;
  }
  public file getfile()
  {
    return file;
  }
  public inputstream getinstream()
  {
    return instream;
  }
  public byte[] getdata()
  {
    return data;
  }
  public string getfilname()
  {
    return filname;
  }
  public void setfilname(string filname)
  {
    this.filname = filname;
  }
  public string getparametername()
  {
    return parametername;
  }
  public void setparametername(string parametername)
  {
    this.parametername = parametername;
  }
  public string getcontenttype()
  {
    return contenttype;
  }
  public void setcontenttype(string contenttype)
  {
    this.contenttype = contenttype;
  }
}

更多关于android相关内容感兴趣的读者可查看本站专题:《android文件操作技巧汇总》、《android操作sqlite数据库技巧总结》、《android操作json格式数据技巧总结》、《android数据库操作技巧总结》、《android编程之activity操作技巧总结》、《android编程开发之sd卡操作方法汇总》、《android开发入门与进阶教程》、《android资源操作技巧汇总》、《android视图view技巧总结》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。