Android 压缩Post请求数据
来源:互联网 发布:电视棒软件安卓版 编辑:程序博客网 时间:2024/04/30 18:16
Android开发中常会用到Post请求发送数据到服务器,有些情况下Post的数据比较大,比如电子市场获取本地应用信息,然后将应用包名,版本号发送给服务器,应用一多,xml数据就庞大了,10KB~30KB都有可能。这是压缩Post的数据就很有必要了。
当然,我们用别的消息格式,如protobuf等效率较高的数据格式也能减少发送的数据,但这会增加服务器和客户端开发人员的工作量,还要花些时间去了解这种数据交换格式。废话不多说,看看下面Post消息体的格式(包含了一个文件上传的Post请求)。
-------------------7d4a6d158c9Content-Disposition: form-data; name="myfile"; filename="test.txt"<this is file content>-------------------7d4a6d158c9Content-Disposition: form-data; name="text1" foo-------------------7d4a6d158c9Content-Disposition: form-data; name="text2" <this is gzipped post field> gzipped size:214 original:416-------------------7d4a6d158c9--
在这个请求体内,name为text2的字段内容采用了gzip压缩,模拟较大的字符串字段。当字符串上10KB压缩量还是挺可观的 ,可减少一倍到四倍的流量。关于怎么构造这个消息体可以参考这里,特别留意这里
Content-Disposition: form-data; name="text2"
的空格,冒号和分号间分别有空格,不然服务器解析会出错,至于为什么?RFC规定就这么地。
下面看看服务器端构造Post消息体(这个是在之前一篇文件上传的文章上增加的功能)
package com.hoot.regx;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;public class PostData {private static final String LONG_STRING = "require 'zlib'equire 'stringio'"+ "File.open('t1.gz', 'w') do |f| gz = Zlib::GzipWriter.new(f)"+ " gz.write 'part one' gz.closeendFile.open('t2.gz', 'w') do |f|"+ " gz = Zlib::GzipWriter.new(f) gz.write 'part 2' gz.close"+ "endcontents1 = File.open('t1.gz', \"rb\") {|io| io.read }"+ "contents2 = File.open('t2.gz', \"rb\") {|io| io.read }"+ "c = contents1 + contents2"+ "gz = Zlib::GzipReader.new(StringIO.new(c))" + "gz.each do | l |"+ " puts l" + "end";private static final String CHAR_SET = "UTF-8";private static final String BOUNDARY = "-----------------7d4a6d158c9";private static final String TWO_HYPHENS = "--";private static final String END = "\r\n";/** * @param args * @throws IOException */public static void main(String[] args) throws IOException {PostData pd = new PostData();pd.uploadFile();// pd.uploadXML();}public void uploadFile() throws IOException {URL url = new URL("http://localhost:4567/upload");HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setRequestMethod("POST");conn.setRequestProperty("Connection", "Keep-Alive");conn.setRequestProperty("Charset", CHAR_SET);conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+ BOUNDARY);StringBuffer sb = new StringBuffer();// 分解符sb.append(TWO_HYPHENS + BOUNDARY + END);// 设置与上次文件相关信息// 上传文件信息和文件的内容间必须有一个空行,否则会把后面的数据当做属性读sb.append("Content-Disposition: form-data; name=\"myfile\"; filename=\"test.txt\""+ END + END);System.out.print(sb.toString());byte[] data = sb.toString().getBytes();OutputStream os = conn.getOutputStream();os.write(data);// 一下是文件数据FileInputStream fis = new FileInputStream(new File("test.txt"));byte[] buf = new byte[1024];int len = 0;while ((len = fis.read(buf)) > 0) {os.write(buf, 0, len);}System.out.print("<this is file content>");/** * 注意form-data后面的空格 -----------------------------7d33a816d302b6 * * Content-Disposition: form-data; name="text1" * * foo -----------------------------7d33a816d302b6 */String split = END + TWO_HYPHENS + BOUNDARY + END+ "Content-Disposition: form-data; " + "name=\"text1\" " + END+ END + "foo"/* + END */;System.out.print(split);os.write(split.getBytes());byte[] b = ZipUtil.compress(LONG_STRING.getBytes());split = END + TWO_HYPHENS + BOUNDARY + END+ "Content-Disposition: form-data; " + "name=\"text2\" " + END+ END/* + dataStr + END */;System.out.print(split);os.write(split.getBytes());os.write(b);os.write(END.getBytes());System.out.print("<this is gzipped post field> gzipped size:" + b.length+ " original:" + LONG_STRING.getBytes().length + END);String endStr = TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + END;byte[] end_data = endStr.getBytes();System.out.print(endStr);os.write(end_data);os.flush();os.close();fis.close();InputStream is = conn.getInputStream();while ((len = is.read(buf)) > 0) {System.out.write(buf, 0, len);}// is.close();}}
以下是压缩字符串的工具类
public static byte[] compress(byte[] data) throws IOException {if (data == null || data.length == 0) {return data;}ByteArrayOutputStream out = new ByteArrayOutputStream();GZIPOutputStream gzip = new GZIPOutputStream(out);gzip.write(data);gzip.close();return out.toByteArray();}
服务器端还是sinatra框架,小巧实用。如果你Servlet顺手,那也无所谓,好久没搞Java EE这套了,忘得差不多了
require 'rubygems'require 'sinatra'require 'haml'require 'zlib'get '/' do 'Hello world'end# Handle GET-request (Show the upload form)get "/upload" do haml :uploadend# Handle POST-request (Receive and save the uploaded file)post "/upload" do logger.info "#{params}" unless params[:myfile] && (tmpfile = params[:myfile][:tempfile]) && (name = params[:myfile][:filename]) @error = "No file selected" logger.info "params #{@error} file: #{tmpfile} name: #{name} #{params}" return haml(:error) end directory = 'uploads' path = File.join(directory, name) logger.info "name:#{params[:text1]}, #{params[:text2]}" #gz = Zlib::GzipReader.new(params[:text2]) #print gz.read #gz.close logger.info inflate(params[:text2]) File.open(path, "wb") do |f| f.write(tmpfile.read) end @msg = "file #{name} was successfully uploaded!"enddef inflate(string) gz = Zlib::GzipReader.new(StringIO.new(params[:text2].force_encoding("UTF-8"))) data = gz.readend
博文源地址在这里,PS:没想到这边阅读量这么高。。。我可怜的VPS上的博客。。。。
- Android 压缩Post请求数据
- android Json数据分装Post请求
- 数据请求get post
- 12、post请求数据
- POST数据请求
- post请求数据
- HttpUrl --post请求数据
- HttpClient --post请求数据
- HttpUrl--post请求数据
- Android向Web服务器发送Post请求并返回数据
- Android向Web服务器发送Post请求并返回数据
- android新增修改数据 采用Post向服务器端发送请求
- Android用httpURLConnection发送post网络请求并拿到数据
- Android 通过Get/Post提交请求数据到服务器
- Android post请求网络数据(json作为参数)
- Android使用HttpURLConnection进行POST请求,向服务器上传数据
- Android中post请求传递json数据给服务端
- Android异步线程OkHttp Post请求Json数据并解析
- 单元测试中的模式
- 【Android基础】Activity的启动模式(android:launchMode)
- android imageview设置图片的小问题
- 将Button的Enabled属性绑定到变量,并使两个不同Button的此属性互斥
- updateprogress用法
- Android 压缩Post请求数据
- 七夕怀念
- 都是奖学金惹的祸
- Baidu:C#利用百度来搜索网页、图片、视频等等
- 杂谈人生
- Oracle 知识点滴
- Linux C调用C++库
- Android之PreferenceActivity
- C++编程之内存和指针