原文地址:http://www.faceye.net/search/96957.html
上传下载文件在浏览器里面都非常简单,上传文件在浏览器里就是几个标签,中间到底发生了什么我们全然不知,而下载文件更是简单——下载文件只需获得文件的地址以二进制的方式写出来就好。最近有个同学想在安卓里面做一个上传功能的App,最简单的莫过于HTTP的POST方法了(fork this )。
可以先观察下上传文件的HTTP Header:
可以看到Request Header后面多了一个没有见过的 Request Payload, 这个Request Payload 正是上传文件的关键,我的理解主要参考 ,这篇文章详细的介绍了他在后台抓取到的POST的信息的格式,对,POST传送文件的时候格式一定要严格,否则就上传不了(我已经做过多次试验),文章里抓到的数据和 Request Payload里的数据差不多,知识Payload里面没有文件的二进制流。
总结一下,POST上传文件的要点:
一、boundary是浏览器随机生成的分隔符(请求头里面有),请求头里面的boundary前面是四个"-",而Payload里面的是六个,多的两个叫做 prefix(前缀),然后就是结束的地方又有两个prefix(怎么感觉应该叫做后缀)
二、换行都是"\r\n"
三、只有最后结束的地方才会多一个前缀,如果是多个文件上传,前面的都一样只有最后一个会多一个前缀
附java实现代码(照着网上的改的):
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class Poster
{
static String boundary = "--------------7d226f700d0";
static String prefix = "--";
static String newLine = "\r\n";
public static void main(String args[])
{
test();
}
private static void test()
{
try
{
URL url = new URL("http://1.crackme.sinaapp.com/scripts/upload.php");//post address
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-type","multipart/form-data;boundary="+boundary);
AssemblyHttp(connection.getOutputStream());
InputStream ins = connection.getInputStream();
byte[] b = readBuffer(ins);
System.out.println(new String(b));
} catch (MalformedURLException e)
{
System.out.println(" URL address error ");
} catch (IOException e)
{
System.out.println(" URL open error ");
}
}
private static void AssemblyHttp(OutputStream out)
{
StringBuffer params = new StringBuffer();
params.append(prefix+boundary + newLine);
//name is the the key "name"'s value in the upload form
params.append("Content-Disposition: form-data; name=\"myfile[]\";filename="+"\"20140821182141.jpg\"");
params.append(newLine);
params.append("Content-Type: image/jpeg");
params.append(newLine+newLine);
StringBuffer params2 = new StringBuffer();
params2.append(prefix+boundary + newLine);
params2.append("Content-Disposition: form-data; name=\"myfile[]\";filename="+"\"6b68a43308f198a375d9369a39c7ee1e.jpg\"");
params2.append(newLine);
params2.append("Content-Type: image/jpeg");
params2.append(newLine+newLine);
File file = new File("C:\\Users\\KL\\Pictures\\20140821182141.jpg");
File file2 = new File("C:\\Users\\KL\\Pictures\\6b68a43308f198a375d9369a39c7ee1e.jpg");
try
{
InputStream in = new FileInputStream(file);
out.write(params.toString().getBytes());
out.write(readBuffer(in));
out.write(newLine.getBytes());
out.write((prefix+boundary+newLine).getBytes());
InputStream in2 = new FileInputStream(file2);
out.write(params2.toString().getBytes());
out.write(readBuffer(in2));
out.write(newLine.getBytes());
out.write((prefix+boundary + prefix).getBytes());
out.flush();
out.close();
} catch (FileNotFoundException e)
{
System.out.println(" file not found ");
} catch (IOException e)
{
System.out.println(" IO Error ");
}
}
public static byte[] readBuffer(InputStream ins) throws IOException
{
byte b[] = new byte[1024];
ByteArrayOutputStream stream = new ByteArrayOutputStream();
int len = 0;
while((len=ins.read(b))!= -1)
{
stream.write(b, 0, len);
}
return stream.toByteArray();
}
}