jsdever 2002/10/01 12:13:42 Added: httpclient/src/java/org/apache/commons/httpclient/methods MultipartPostMethod.java httpclient/src/java/org/apache/commons/httpclient/methods/multipart FilePart.java Part.java StringPart.java Log: Add multipart POST support. Added a new class methods/MultiPartPost and some related classes in the methods/multipart package. http://www.mail-archive.com/commons-dev@jakarta.apache.org/msg01701.html http://nagoya.apache.org/bugzilla/show_bug.cgi?id=13165 Contributed by: Matthew Albright Revision Changes Path 1.1 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/MultipartPostMethod.java Index: MultipartPostMethod.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/MultipartPostMethod.java,v 1.1 2002/10/01 19:13:41 jsdever Exp $ * $Revision: 1.1 $ * $Date: 2002/10/01 19:13:41 $ * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1992 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "HttpClient", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.commons.httpclient.methods; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.io.File; import java.io.OutputStream; import java.io.IOException; import java.io.FileNotFoundException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.multipart.*; /** * POST Method for Multipart encoded forms. * * @author <a href="mailto:[EMAIL PROTECTED]">Matthew Albright</a> * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Dever</a> * * @since 2.0 */ public class MultipartPostMethod extends GetMethod { private List parameters = new ArrayList(); /** * No-arg constructor. */ public MultipartPostMethod() { super(); } /** * Path-setting constructor. * @param path the path to request */ public MultipartPostMethod(String path) { super(path); } /** * Constructor. * @param path the path to request * @param tempDir directory to store temp files in */ public MultipartPostMethod(String path, String tempDir) { super(path, tempDir); } /** * Constructor. * @param path the path to request * @param tempDir directory to store temp files in * @param tempFile file to store temporary data in */ public MultipartPostMethod(String path, String tempDir, String tempFile) { super(path, tempDir, tempFile); } /** * Returns <tt>"POST"</tt>. * @return <tt>"POST"</tt> */ public String getName() { return "POST"; } /** * Clear my request body. */ public void recycle() { super.recycle(); parameters.clear(); } public void addParameter(String parameterName, String parameterValue) { Part param = new StringPart(parameterName, parameterValue); parameters.add(param); } public void addParameter(String parameterName, File parameterFile) throws FileNotFoundException { Part param = new FilePart(parameterName, parameterFile); parameters.add(param); } protected void addRequestHeaders(HttpState state, HttpConnection conn) throws IOException, HttpException { super.addRequestHeaders(state,conn); if (! parameters.isEmpty()) { setRequestHeader("Content-Type", "multipart/form-data; boundary=" + Part.getBoundary()); } } /** * Override method of {@link HttpMethodBase} * to write request parameters as the * request body. */ protected boolean writeRequestBody(HttpState state, HttpConnection conn) throws IOException, HttpException { OutputStream out = conn.getRequestOutputStream(); for (Iterator it = parameters.iterator(); it.hasNext();) { Part part = (Part)it.next(); part.send(out); } Part.sendLastBoundary(out); out.close(); return true; } /** * Override method of {@link HttpMethodBase} * to return the length of the request body. * * Once this method has been invoked, * the request parameters cannot be altered * until I am {@link #recycle recycled}. */ protected int getRequestContentLength() { long length = 0; try { for (Iterator it = parameters.iterator(); it.hasNext();) { Part part = (Part)it.next(); length += part.length(); } length += Part.lengthOfLastBoundary(); } catch (IOException e) { // Can't throw an IOException and still override throw new RuntimeException(e.toString()); } // Chop the length to the max int value. if (length <= Integer.MAX_VALUE) { return((new Long(length)).intValue()); } else { return(Integer.MAX_VALUE); } } } 1.1 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java Index: FilePart.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java,v 1.1 2002/10/01 19:13:41 jsdever Exp $ * $Revision: 1.1 $ * $Date: 2002/10/01 19:13:41 $ * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "HttpClient", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.commons.httpclient.methods.multipart; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * This class implements a part of a Multipart post object that * consists of a file. * * It makes every effort to not parse or store * any of the data in the file, in order to not munge a binary file, * and to not break if the file is huge. Hence, use a simple byte * array, and just shove it down the OutputStream. * * @author <a href="mailto:[EMAIL PROTECTED]">Matthew Albright</a> * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Dever</a> * * @since 2.0 * */ public class FilePart extends Part { //TODO: make this configurable static int MAX_BUFF_SIZE = 1 * 1024 * 1024; // 1 MiBs private String name; private File file; private int buff_size; /** * Constructor. * * @param name * @param file the file to post * * @throws FileNotFoundException if the <i>file</i> is not is normal * file or if it is not readable. */ public FilePart(String name, File file) throws FileNotFoundException { if (! file.isFile()) { throw new FileNotFoundException("File is not a normal file."); } if (! file.canRead()) { throw new FileNotFoundException("File is not readable."); } this.name = name; this.file = file; } protected void sendHeader(OutputStream out) throws IOException { super.sendHeader(out); sendFilename(out); sendContentType(out); } protected void sendFilename(OutputStream out) throws IOException { String filename = "; filename=\"" + file.getName() + "\""; out.write(filename.getBytes()); } protected void sendContentType(OutputStream out) throws IOException { out.write(CRLF_bytes); out.write("Content-Type: application/octet-stream".getBytes()); } public String getName() { return name; } protected void sendData(OutputStream out) throws IOException { byte[] buff; if (lengthOfData() > MAX_BUFF_SIZE) { buff = new byte[MAX_BUFF_SIZE]; } else { buff = new byte[(new Long(lengthOfData())).intValue()]; } InputStream in; try { in = new FileInputStream(file); int len; while ((len = in.read(buff)) != -1) { out.write(buff, 0, len); } } catch (FileNotFoundException e) { throw new IOException(e.toString()); } } protected long lengthOfData() throws IOException { return file.length(); } } 1.1 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java Index: Part.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java,v 1.1 2002/10/01 19:13:41 jsdever Exp $ * $Revision: 1.1 $ * $Date: 2002/10/01 19:13:41 $ * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "HttpClient", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.commons.httpclient.methods.multipart; import java.io.OutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * Abstract class for one Part of a multipart post object. * * @author <a href="mailto:[EMAIL PROTECTED]">Matthew Albright</a> * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Dever</a> * * @since 2.0 */ public abstract class Part { static String boundary = "----------------314159265358979323846"; static byte[] boundary_bytes = boundary.getBytes(); static String CRLF = "\r\n"; static byte[] CRLF_bytes = CRLF.getBytes(); static String extra = "--"; static byte[] extra_bytes = extra.getBytes(); public static String getBoundary() { return boundary; } public static void sendLastBoundary(OutputStream out) throws IOException { out.write(extra_bytes); out.write(boundary_bytes); out.write(extra_bytes); out.write(CRLF_bytes); } public static int lengthOfLastBoundary() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); sendLastBoundary(out); return(out.size()); } public abstract String getName(); protected void sendStart(OutputStream out) throws IOException { out.write(extra_bytes); out.write(boundary_bytes); out.write(CRLF_bytes); } protected int lengthOfStart() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); sendStart(out); return(out.size()); } protected void sendHeader(OutputStream out) throws IOException { String content_dispos = "Content-Disposition: form-data; name=\"" + getName() + "\""; out.write(content_dispos.getBytes()); } protected int lengthOfHeader() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); sendHeader(out); return(out.size()); } protected void sendEndOfHeader(OutputStream out) throws IOException { out.write(CRLF_bytes); out.write(CRLF_bytes); } protected int lengthOfEndOfHeader() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); sendEndOfHeader(out); return out.size(); } protected abstract void sendData(OutputStream out) throws IOException; protected abstract long lengthOfData() throws IOException; protected void sendEnd(OutputStream out) throws IOException { out.write(CRLF_bytes); } protected int lengthOfEnd() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); sendEnd(out); return out.size(); } /* The following 2 methods don't need to be final, but they DO need * to be overridden as a pair, and the only way to make sure of that * is to make sure they AREN'T overridden. */ final public void send(OutputStream out) throws IOException { sendStart(out); sendHeader(out); sendEndOfHeader(out); sendData(out); sendEnd(out); } final public long length() throws IOException { return lengthOfStart() + lengthOfHeader() + lengthOfEndOfHeader() + lengthOfData() + lengthOfEnd(); } } 1.1 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java Index: StringPart.java =================================================================== /* * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java,v 1.1 2002/10/01 19:13:41 jsdever Exp $ * $Revision: 1.1 $ * $Date: 2002/10/01 19:13:41 $ * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "HttpClient", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.commons.httpclient.methods.multipart; import java.io.OutputStream; import java.io.IOException; /** * Simple string parameter for a multipart post * * @author <a href="mailto:[EMAIL PROTECTED]">Matthew Albright</a> * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Dever</a> * * @since 2.0 */ public class StringPart extends Part { private String name; private String value; /** * @param name * @param value the string to post */ public StringPart(String name, String value) { this.name = name; this.value = value; } public String getName() { return name; } protected void sendData(OutputStream out) throws IOException { out.write(value.getBytes()); } protected long lengthOfData() throws IOException { return value.getBytes().length; } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>