Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6191991

Upload of a file via the multipart output stream.

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Unresolved
    • Icon: P4 P4
    • None
    • 1.4.2
    • core-libs
    • x86
    • windows_xp

      A DESCRIPTION OF THE REQUEST :
      This class (see attched code) allows the upload of a file via the multipart stream.

      JUSTIFICATION :
      It would be a great enahcnemnt for the core java io classes!


      ---------- BEGIN SOURCE ----------
      package com.meridian.mdss.etc;
      import java.io.BufferedReader;
      import java.io.DataOutputStream;
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.InputStream;
      import java.io.InputStreamReader;
      import java.io.OutputStream;
      import java.net.HttpURLConnection;
      import java.net.URL;
      import java.net.URLConnection;

      /**
       * <code>MultiPartFormOutputStream</code> is used to write
       * "multipart/form-data" to a <code>java.net.URLConnection</code> for
       * POSTing. This is primarily for file uploading to HTTP servers.
       *
       * @since JDK1.3
       *
       * http://forum.java.sun.com/thread.jsp?forum=31&thread=451245
       *
       */

      public class MultiPartFormOutputStream{
         
         /**
          * The line end characters.
          */
         private static final String NEWLINE = "\r\n";

         /**
          * The boundary prefix.
          */
         private static final String PREFIX = "--";

         /**
          * The output stream to write to.
          */
         private DataOutputStream out = null;

         /**
          * The multipart boundary string.
          */
         private String boundary = null;

         /**
          * Creates a new <code>MultiPartFormOutputStream</code> object using
          * the specified output stream and boundary. The boundary is required
          * to be created before using this method, as described in the
          * description for the <code>getContentType(String)</code> method.
          * The boundary is only checked for <code>null</code> or empty string,
          * but it is recommended to be at least 6 characters. (Or use the
          * static createBoundary() method to create one.)
          *
          * @param os the output stream
          * @param boundary the boundary
          * @see #createBoundary()
          * @see #getContentType(String)
          */
         public MultiPartFormOutputStream(OutputStream os, String boundary) {
            if(os == null){
               throw new IllegalArgumentException("Output stream is required.");
            }
            if(boundary == null || boundary.length() == 0){
               throw new IllegalArgumentException("Boundary stream is required.");
            }
            this.out = new DataOutputStream(os);
            this.boundary = boundary;
         }

         /**
          * Writes an boolean field value.
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, boolean value) throws java.io.IOException{
            writeField(name, new Boolean(value).toString());
         }

         /**
          * Writes an double field value.
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, double value) throws java.io.IOException{
            writeField(name, Double.toString(value));
         }

         /**
          * Writes an float field value.
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, float value) throws java.io.IOException{
            writeField(name, Float.toString(value));
         }

         /**
          * Writes an long field value.
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, long value) throws java.io.IOException{
            writeField(name, Long.toString(value));
         }

         /**
          * Writes an int field value.
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, int value) throws java.io.IOException{
            writeField(name, Integer.toString(value));
         }

         /**
          * Writes an short field value.
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, short value) throws java.io.IOException{
            writeField(name, Short.toString(value));
         }

         /**
          * Writes an char field value.
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, char value) throws java.io.IOException{
            writeField(name, new Character(value).toString());
         }

         /**
          * Writes an string field value. If the value is null, an empty string
          * is sent ("").
          *
          * @param name the field name (required)
          * @param value the field value
          * @throws java.io.IOException on input/output errors
          */
         public void writeField(String name, String value) throws java.io.IOException{
            if(name == null){
               throw new IllegalArgumentException("Name cannot be null or empty.");
            }
            if(value == null){
               value = "";
            }
            /*
             --boundary\r\n
             Content-Disposition: form-data; name="<fieldName>"\r\n
             \r\n
             <value>\r\n
             */
            // write boundary
            out.writeBytes(PREFIX);
            out.writeBytes(boundary);
            out.writeBytes(NEWLINE);
            // write content header
            out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"");
            out.writeBytes(NEWLINE);
            out.writeBytes(NEWLINE);
            // write content
            out.writeBytes(value);
            out.writeBytes(NEWLINE);
            out.flush();
         }

         /**
          * Writes a file's contents. If the file is null, does not exists, or
          * is a directory, a <code>java.lang.IllegalArgumentException</code>
          * will be thrown.
          *
          * @param name the field name
          * @param mimeType the file content type (optional, recommended)
          * @param file the file (the file must exist)
          * @throws java.io.IOException on input/output errors
          */
         public void writeFile(String name, String mimeType, File file) throws java.io.IOException{
            if(file == null){
               throw new IllegalArgumentException("File cannot be null.");
            }
            if(!file.exists()){
               throw new IllegalArgumentException("File does not exist.");
            }
            if(file.isDirectory()){
               throw new IllegalArgumentException("File cannot be a directory.");
            }
            writeFile(name, mimeType, file.getCanonicalPath(), new FileInputStream(file));
         }

         /**
          * Writes a input stream's contents. If the input stream is null, a
          * <code>java.lang.IllegalArgumentException</code> will be thrown.
          *
          * @param name the field name
          * @param mimeType the file content type (optional, recommended)
          * @param fileName the file name (required)
          * @param is the input stream
          * @throws java.io.IOException on input/output errors
          */
         public void writeFile(String name, String mimeType, String fileName, InputStream is) throws java.io.IOException{
            if(is == null){
               throw new IllegalArgumentException("Input stream cannot be null.");
            }
            if(fileName == null || fileName.length() == 0){
               throw new IllegalArgumentException("File name cannot be null or empty.");
            }
            /*
             --boundary\r\n
             Content-Disposition: form-data; name="<fieldName>"; filename="<filename>"\r\n
             Content-Type: <mime-type>\r\n
             \r\n
             <file-data>\r\n
             */
            // write boundary
            out.writeBytes(PREFIX);
            out.writeBytes(boundary);
            out.writeBytes(NEWLINE);
            // write content header
            out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\" filename=\"" + fileName + "\"");
            out.writeBytes(NEWLINE);
            if(mimeType != null){
               out.writeBytes("Content-Type: " + mimeType);
               out.writeBytes(NEWLINE);
            }
            out.writeBytes(NEWLINE);
            // write content
            byte[] data = new byte[1024];
            int r = 0;
            while ((r = is.read(data, 0, data.length)) != -1){
               out.write(data, 0, r);
            }
            // close input stream, but ignore any possible exception for it
            try{
               is.close();
            }catch (Exception e){}
            out.writeBytes(NEWLINE);
            out.flush();
         }

         /**
          * Writes the given bytes. The bytes are assumed to be the contents
          * of a file, and will be sent as such. If the data is null, a
          * <code>java.lang.IllegalArgumentException</code> will be thrown.
          *
          * @param name the field name
          * @param mimeType the file content type (optional, recommended)
          * @param fileName the file name (required)
          * @param data the file data
          * @throws java.io.IOException on input/output errors
          */
         public void writeFile(String name, String mimeType, String fileName, byte[] data) throws java.io.IOException{
            if(data == null){
               throw new IllegalArgumentException("Data cannot be null.");
            }
            if(fileName == null || fileName.length() == 0){
               throw new IllegalArgumentException("File name cannot be null or empty.");
            }
            /*
             --boundary\r\n
             Content-Disposition: form-data; name="<fieldName>"; filename="<filename>"\r\n
             Content-Type: <mime-type>\r\n
             \r\n
             <file-data>\r\n
             */
            // write boundary
            out.writeBytes(PREFIX);
            out.writeBytes(boundary);
            out.writeBytes(NEWLINE);
            // write content header
            out.writeBytes("Content-Disposition: form-data; name=\"" + name + "\" filename=\"" + fileName + "\"");
            out.writeBytes(NEWLINE);
            if(mimeType != null){
               out.writeBytes("Content-Type: " + mimeType);
               out.writeBytes(NEWLINE);
            }
            out.writeBytes(NEWLINE);
            // write content
            out.write(data, 0, data.length);
            out.writeBytes(NEWLINE);
            out.flush();
         }

         /**
          * Flushes the stream. Actually, this method does nothing, as the only
          * write methods are highly specialized and automatically flush.
          *
          * @throws java.io.IOException on input/output errors
          */
         public void flush() throws java.io.IOException{
         // out.flush();
         }

         /**
          * Closes the stream. <br />
          * <br />
          * <b>NOTE:</b> This method <b>MUST</b> be called to finalize the
          * multipart stream.
          *
          * @throws java.io.IOException on input/output errors
          */
         public void close() throws java.io.IOException{
            // write final boundary
            out.writeBytes(PREFIX);
            out.writeBytes(boundary);
            out.writeBytes(PREFIX);
            out.writeBytes(NEWLINE);
            out.flush();
            out.close();
         }

         /**
          * Gets the multipart boundary string being used by this stream.
          *
          * @return the boundary
          */
         public String getBoundary(){
            return this.boundary;
         }

         /**
          * Creates a new <code>java.net.URLConnection</code> object from the
          * specified <code>java.net.URL</code>. This is a convenience method
          * which will set the <code>doInput</code>, <code>doOutput</code>,
          * <code>useCaches</code> and <code>defaultUseCaches</code> fields to
          * the appropriate settings in the correct order.
          *
          * @return a <code>java.net.URLConnection</code> object for the URL
          * @throws java.io.IOException on input/output errors
          */
         public static URLConnection createConnection(URL url) throws java.io.IOException{
            URLConnection urlConn = url.openConnection();
            if(urlConn instanceof HttpURLConnection){
               HttpURLConnection httpConn = (HttpURLConnection)urlConn;
               httpConn.setRequestMethod("POST");
            }
            urlConn.setDoInput(true);
            urlConn.setDoOutput(true);
            urlConn.setUseCaches(false);
            urlConn.setDefaultUseCaches(false);
            return urlConn;
         }

         /**
          * Creates a multipart boundary string by concatenating 20 hyphens (-)
          * and the hexadecimal (base-16) representation of the current time in
          * milliseconds.
          *
          * @return a multipart boundary string
          * @see #getContentType(String)
          */
         public static String createBoundary(){
            return "--------------------" + Long.toString(System.currentTimeMillis(), 16);
         }

         /**
          * Gets the content type string suitable for the
          * <code>java.net.URLConnection</code> which includes the multipart
          * boundary string. <br />
          * <br />
          * This method is static because, due to the nature of the
          * <code>java.net.URLConnection</code> class, once the output stream
          * for the connection is acquired, it's too late to set the content
          * type (or any other request parameter). So one has to create a
          * multipart boundary string first before using this class, such as
          * with the <code>createBoundary()</code> method.
          *
          * @param boundary the boundary string
          * @return the content type string
          * @see #createBoundary()
          */
         public static String getContentType(String boundary){
            return "multipart/form-data; boundary=" + boundary;
         }

         //Test method
         public static void main(String[] args) throws Exception{
            URL url = new URL("http://www.domain.com/webems/upload.do");
            //--create a boundary string
            String boundary = MultiPartFormOutputStream.createBoundary();
            URLConnection urlConn = MultiPartFormOutputStream.createConnection(url);
            urlConn.setRequestProperty("Accept", "*/*");
            urlConn.setRequestProperty("Content-Type", MultiPartFormOutputStream.getContentType(boundary));
            //--set some other request headers...
            urlConn.setRequestProperty("Connection", "Keep-Alive");
            urlConn.setRequestProperty("Cache-Control", "no-cache");
            //--no need to connect cuz getOutputStream() does it
            MultiPartFormOutputStream out = new MultiPartFormOutputStream(urlConn.getOutputStream(), boundary);
            //--write a text field element
            out.writeField("myText", "text field text");
            //--upload a file
            out.writeFile("myFile", "text/plain", new File("C:\\test.txt"));
            //--can also write bytes directly
            //out.writeFile("myFile", "text/plain", "C:\\test.txt",
            //"This is some file text.".getBytes("ASCII"));
            out.close();
            //--read response from server
            BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
            String line = "";
            while ((line = in.readLine()) != null){
               System.out.println(line);
            }
            in.close();
         }
      }
      ---------- END SOURCE ----------
      ###@###.### 2004-11-08 06:24:54 GMT

            Unassigned Unassigned
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: