package org.nutz.http.sender; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.Map.Entry; import org.nutz.http.HttpException; import org.nutz.http.Request; import org.nutz.http.Response; import org.nutz.lang.ContinueLoop; import org.nutz.lang.Each; import org.nutz.lang.ExitLoop; import org.nutz.lang.Lang; import org.nutz.lang.LoopException; import org.nutz.lang.Streams; import org.nutz.lang.random.R; public class FilePostSender extends PostSender { public static final String SEPARATOR = "\r\n"; public FilePostSender(Request request) { super(request); } public static FilePostSender create(Request request) { return new FilePostSender(request); } @Override public Response send() throws HttpException { try { String boundary = "------FormBoundary" + R.UU32(); openConnection(); setupRequestHeader(); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); setupDoInputOutputFlag(); Map<String, Object> params = request.getParams(); if (null != params && params.size() > 0) { export(params, getOutputStream(), boundary, request.getEnc()); } return createResponse(getResponseHeader()); } catch (IOException e) { throw new HttpException(request.getUrl().toString(), e); } } public static void export(Map<String, Object> params, OutputStream out, final String boundary, final String enc) throws IOException { final DataOutputStream outs = new DataOutputStream(out); for (Entry<String, ?> entry : params.entrySet()) { final String key = entry.getKey(); Object val = entry.getValue(); if (val == null) val = ""; Lang.each(val, new Each<Object>() { @Override public void invoke(int index, Object ele, int length) throws ExitLoop, ContinueLoop, LoopException { try { outs.writeBytes("--" + boundary + SEPARATOR); if (ele != null && ele instanceof File) { writeFile((File)ele, key, outs, boundary, enc); return; } outs.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"" + SEPARATOR + SEPARATOR); outs.write(String.valueOf(ele).getBytes(enc)); outs.writeBytes(SEPARATOR); } catch (Exception e) { throw Lang.wrapThrow(e); } } }); } outs.writeBytes("--" + boundary + "--" + SEPARATOR); Streams.safeFlush(outs); Streams.safeClose(outs); } protected static void writeFile(File f, String key, DataOutputStream outs, String boundary, final String enc) throws IOException { outs.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"; filename=\""); outs.write(f.getName().getBytes(enc)); outs.writeBytes("\"" + SEPARATOR); String ct = "application/octet-stream"; if (f.getName().endsWith(".jpg")) { ct = "image/jpeg"; } outs.writeBytes("Content-Type: " + ct + SEPARATOR + SEPARATOR); InputStream is = null; try { is = Streams.fileIn(f); Streams.write(outs, is); outs.writeBytes(SEPARATOR); } finally { Streams.safeClose(is); } } @Override public int getEstimationSize() throws IOException { final int[] count = new int[1]; for (Entry<String, ?> entry : request.getParams().entrySet()) { count[0] += 60; final String key = entry.getKey(); Object val = entry.getValue(); if (val == null) val = ""; Lang.each(val, new Each<Object>() { public void invoke(int index, Object ele, int length){ if (ele instanceof File) count[0]+= ((File)ele).length() + 100; else try { count[0] += (key+ele).getBytes(request.getEnc()).length + 100; } catch (UnsupportedEncodingException e) { } } }); } return count[0]; } }