• 模拟POST上传文件


      上传下载文件在浏览器里面都非常简单,上传文件在浏览器里就是几个标签,中间到底发生了什么我们全然不知,而下载文件更是简单——下载文件只需获得文件的地址以二进制的方式写出来就好。最近有个同学想在安卓里面做一个上传功能的App,最简单的莫过于HTTP的POST方法了(fork this  https://www.imququ.com/post/four-ways-to-post-data-in-http.html)。

      可以先观察下上传文件的HTTP Header:

    可以看到Request Header后面多了一个没有见过的 Request Payload, 这个Request Payload 正是上传文件的关键,我的理解主要参考 http://jackface.iteye.com/blog/2098604,这篇文章详细的介绍了他在后台抓取到的POST的信息的格式,对,POST传送文件的时候格式一定要严格,否则就上传不了(我已经做过多次试验),文章里抓到的数据和 Request Payload里的数据差不多,知识Payload里面没有文件的二进制流。

      总结一下,POST上传文件的要点:   

      一、boundary是浏览器随机生成的分隔符(请求头里面有),请求头里面的boundary前面是四个"-",而Payload里面的是六个,多的两个叫做 prefix(前缀),然后就是结束的地方又有两个prefix(怎么感觉应该叫做后缀)

      二、换行都是" "

      三、只有最后结束的地方才会多一个前缀,如果是多个文件上传,前面的都一样只有最后一个会多一个前缀

    附java实现代码(照着网上的改的):

      1 import java.io.ByteArrayOutputStream;
      2 import java.io.File;
      3 import java.io.FileInputStream;
      4 import java.io.FileNotFoundException;
      5 import java.io.IOException;
      6 import java.io.InputStream;
      7 import java.io.OutputStream;
      8 import java.net.HttpURLConnection;
      9 import java.net.MalformedURLException;
     10 import java.net.URL;
     11 
     12 public class Poster
     13 {
     14   static String boundary = "--------------7d226f700d0";
     15   static String prefix = "--";
     16   static String newLine = "
    ";
     17   public static void main(String args[])
     18   {
     19     test();
     20   }
     21   private static void test()
     22   {
     23     try
     24     {
     25       
     26       URL url = new URL("http://1.crackme.sinaapp.com/scripts/upload.php");//post address
     27       HttpURLConnection connection = (HttpURLConnection) url.openConnection();
     28       connection.setDoInput(true);
     29       connection.setDoOutput(true);
     30 
     31       connection.setRequestProperty("Content-type","multipart/form-data;boundary="+boundary); 
     32       AssemblyHttp(connection.getOutputStream());
     33       InputStream ins = connection.getInputStream();
     34       byte[] b = readBuffer(ins);
     35       System.out.println(new String(b));
     36     } catch (MalformedURLException e)
     37     {
     38       System.out.println(" URL address error ");
     39     } catch (IOException e)
     40     {
     41       System.out.println(" URL open error ");
     42     }
     43   }
     44   private static void AssemblyHttp(OutputStream out)
     45   {
     46     StringBuffer params = new StringBuffer();
     47       
     48     params.append(prefix+boundary + newLine);
     49                                                   //name is the the key "name"'s value in the upload form
     50     params.append("Content-Disposition: form-data; name="myfile[]";filename="+""20140821182141.jpg"");
     51     params.append(newLine);       
     52     params.append("Content-Type: image/jpeg");
     53     params.append(newLine+newLine);
     54     
     55     StringBuffer params2 = new StringBuffer();
     56       
     57     params2.append(prefix+boundary + newLine);
     58                                                                 
     59     params2.append("Content-Disposition: form-data; name="myfile[]";filename="+""6b68a43308f198a375d9369a39c7ee1e.jpg"");
     60     params2.append(newLine);       
     61     params2.append("Content-Type: image/jpeg");
     62     params2.append(newLine+newLine);
     63 
     64 
     65     File file = new File("C:\Users\KL\Pictures\20140821182141.jpg");
     66     File file2 = new File("C:\Users\KL\Pictures\6b68a43308f198a375d9369a39c7ee1e.jpg");
     67     try
     68     {
     69       InputStream in = new FileInputStream(file);
     70       out.write(params.toString().getBytes());                   
     71       out.write(readBuffer(in));
     72       out.write(newLine.getBytes());           
     73       out.write((prefix+boundary+newLine).getBytes());
     74 
     75 
     76       InputStream in2 = new FileInputStream(file2);
     77       out.write(params2.toString().getBytes());                   
     78       out.write(readBuffer(in2));
     79       out.write(newLine.getBytes());
     80 
     81       out.write((prefix+boundary + prefix).getBytes());
     82       out.flush();
     83       out.close();         
     84     } catch (FileNotFoundException e)
     85     {
     86       System.out.println(" file not found  ");
     87     } catch (IOException e)
     88     {
     89       System.out.println(" IO Error ");
     90     }
     91   }
     92 
     93 
     94   public static byte[] readBuffer(InputStream ins) throws IOException
     95   {
     96     byte b[] = new byte[1024];
     97     ByteArrayOutputStream stream = new ByteArrayOutputStream();
     98     int len = 0;
     99     while((len=ins.read(b))!= -1)
    100     {
    101       stream.write(b, 0, len);
    102     }
    103     return stream.toByteArray();
    104   }
    105 }
    View Code

    用java写可以看到好多上传的细节,用Python的第三方库就非常简洁了,libcurl(fork this http://curl.haxx.se/libcurl/)有python的移植但是有点太庞大的,配置起来也不好配置,poster 也是python的一个第三方库,用起来非常方便,代码如下:

     1 # test_client.py
     2 from poster.encode import multipart_encode
     3 from poster.streaminghttp import register_openers
     4 import urllib2
     5 
     6 url = ["http://1.crackme.sinaapp.com/scripts/upload.php","http://localhost/learnPHP/scripts/upload.php"]
     7 
     8 register_openers()
     9 
    10 
    11 datagen, headers = multipart_encode({"myfile": open("C:\Users\KL\Pictures\20140821182141.jpg", "rb")})
    12 
    13 
    14 request = urllib2.Request(url[0], datagen, headers)
    15 
    16 print urllib2.urlopen(request).read()
    View Code

    (fork this http://alexliyu.blog.163.com/blog/static/162754496201252154412432/

  • 相关阅读:
    .NetCore Grpc 客服端 工厂模式配置授权
    DOCKER 拉取 dotnet 镜像太慢 docker pull mcr.microsoft.com too slow
    Introducing .NET 5
    VSCode 出现错误 System.IO.IOException: The configured user limit (128) on the number of inotify instances has been reached.
    Omnisharp VsCode Attaching to remote processes
    zookeeper3.5.5 centos7 完全分布式 搭建随记
    Hadoop2.7.7 centos7 完全分布式 配置与问题随记
    MySQL索引 索引分类 最左前缀原则 覆盖索引 索引下推 联合索引顺序
    SQL基础随记3 范式 键
    MySQL调优 优化需要考虑哪些方面
  • 原文地址:https://www.cnblogs.com/pasion-forever/p/3975862.html
Copyright © 2020-2023  润新知