自己构造http消息体,用HttpConnection实现文件上传, 后台用的是Sinatra框架搞定服务端,很简洁,几行代码,比起servlet快捷不少
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; import java.util.List; import java.util.Map; import java.util.Map.Entry; public class Regx { 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 { 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", "UTF-8"); 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); //上传文件信息和文件的内容间必须有一个空行 sb.append(END); // Map<String, List<String>> props = conn.getRequestProperties(); // for(Entry<String, List<String>> prop : props.entrySet()){ // System.out.println(prop.getKey() + ":" ); // for(String str : prop.getValue()){ // System.out.print(str); // } // System.out.println(); // } System.out.println(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); } String endStr = END + TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + END; byte[] end_data = endStr.getBytes(); System.out.println("<this is file content>"); System.out.println(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(); } }
服务器端:
需要安装几个gem
sinatra haml
require 'rubygems' require 'sinatra' require 'haml' get '/' do 'Hello world' end # Handle GET-request (Show the upload form) get "/upload" do haml :upload end # 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) File.open(path, "wb") do |f| f.write(tmpfile.read) end #File.copy(tempfile.path, path) @msg = "#{name}The file was successfully uploaded!" end
够简洁吧,下面我吧两个haml文件也贴一下(haml文件放在在同级目录的views目录下)
upload.haml
%html %body %h1 File uploader! %form(method="post" enctype='multipart/form-data') %input(type='file' name='myfile') %br %input(type='submit' value='Upload!')
error.haml
%html %body %h1 File uploader error!
总结:自己构造Post请求有些繁琐,分隔符间空格很重要,如过看不明白可以用抓包工具传两个小文件 然后看看浏览器构造的请求体是什么格式,然后我们用字符串片接方式构造相同的结构,发送给服务器。
参考资料http://my.oschina.net/u/226973/blog/48897 sinatrarb.comhaml.info