【问题标题】:Using GoogleHttpClient to send multipart/form-data使用 GoogleHttpClient 发送 multipart/form-data
【发布时间】:2013-04-09 10:49:52
【问题描述】:

我正在使用 google-http-client for java 来处理 Android 上的 http 连接。

到目前为止,一切都是 HunkyDori直到尝试发送 multipart/form-data 内容。

我有点卡住了,我正在考虑调整 MultipartContent 类来创建我自己的 MultipartFormContent 版本。

我需要一个MultipartEntity 的版本,它可以像这样有效地工作:

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);

FileBody bin = new FileBody(new File(fileName));
StringBody comment = new StringBody("Filename: " + fileName);

MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("bin", bin);
reqEntity.addPart("comment", comment);
httppost.setEntity(reqEntity);

HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();

通过阅读,multipart/relativemultipart/form 之间的唯一区别是打印输出时添加名称?

任何人都对调整 MultipartContent 类以支持“名称”字段有任何想法。

问候。

【问题讨论】:

    标签: android google-http-client


    【解决方案1】:

    好的,我基于 MultipartContent 类创建了以下类:

    /**
     * Serializes MIME multipart content to the form-data standard. Adapated from {@link MultipartContent}
     * <p/>
     * <p>
     * By default the media type is {@code "multipart/form-data; boundary=__END_OF_PART__"}, but this may
     * be customized by calling {@link #setMediaType(HttpMediaType)}, {@link #getMediaType()}, or
     * {@link #setBoundary(String)}.
     * </p>
     * <p/>
     * <p>
     * Implementation is not thread-safe.
     * </p>
     *
     * @author Christopher Jenkins
     * @since 1.15
     */
    public class MultipartFormContent extends AbstractHttpContent
    {
    
        static final String NEWLINE = "\r\n";
        private static final String TWO_DASHES = "--";
        /**
         * Parts of the HTTP multipart request.
         */
        private ArrayList<Part> parts = new ArrayList<Part>();
    
        public MultipartFormContent()
        {
            super(new HttpMediaType("multipart/form-data").setParameter("boundary", "__END_OF_PART__"));
        }
    
        public void writeTo(OutputStream out) throws IOException
        {
            Writer writer = new OutputStreamWriter(out, getCharset());
            String boundary = getBoundary();
    
            //TODO use http headers again like MultipartContent
            HttpHeaders headers;
            String contentDisposition = null;
            HttpContent content = null;
            StreamingContent streamingContent = null;
            for (Part part : parts)
            {
                // analyze the headers
                headers = new HttpHeaders().setAcceptEncoding(null);
                if (part.headers != null)
                    headers.fromHttpHeaders(part.headers);
                headers.setContentEncoding(null)
                        .setUserAgent(null)
                        .setContentType(null)
                        .setContentLength(null)
                        .set("Content-Transfer-Encoding", null);
    
                // Write disposition
                if (part.getName() != null)
                {
                    contentDisposition = String.format("form-data; name=\"%s\"", part.name);
                    // Do we have a filename?
                    // Then add to the content dispos
                    if (part.filename != null)
                        contentDisposition += String.format("; filename=\"%s\"", part.filename);
                    headers.set("Content-Disposition", contentDisposition);
                }
    
                // analyze the content
                content = part.content;
                streamingContent = null;
                if (content != null)
                {
                    headers.setContentType(content.getType());
                    headers.set("Content-Transfer-Encoding", Arrays.asList("binary"));
                    final HttpEncoding encoding = part.encoding;
                    if (encoding == null)
                        streamingContent = content;
                    else
                    {
                        headers.setContentEncoding(encoding.getName());
                        streamingContent = new HttpEncodingStreamingContent(content, encoding);
                    }
                }
    
                // write separator
                writer.write(TWO_DASHES);
                writer.write(boundary);
                writer.write(NEWLINE);
                // Write Headers
                HttpHeaders.serializeHeadersForMultipartRequests(headers, null, null, writer);
                // write content
                if (streamingContent != null)
                {
                    writer.write(NEWLINE);
                    writer.flush();
                    streamingContent.writeTo(out);
                    writer.write(NEWLINE);
                }
            }
            // write end separator
            writer.write(TWO_DASHES);
            writer.write(boundary);
            writer.write(TWO_DASHES);
            writer.write(NEWLINE);
            writer.flush();
        }
    
        @Override
        public boolean retrySupported()
        {
            for (Part part : parts)
            {
                if (!part.content.retrySupported())
                {
                    return false;
                }
            }
            return true;
        }
    
        @Override
        public MultipartFormContent setMediaType(HttpMediaType mediaType)
        {
            super.setMediaType(mediaType);
            return this;
        }
    
        /**
         * Returns an unmodifiable view of the parts of the HTTP multipart request.
         */
        public final Collection<Part> getParts()
        {
            return Collections.unmodifiableCollection(parts);
        }
    
        /**
         * Sets the parts of the HTTP multipart request.
         * <p/>
         * <p>
         * Overriding is only supported for the purpose of calling the super implementation and changing
         * the return type, but nothing else.
         * </p>
         */
        public MultipartFormContent setParts(Collection<Part> parts)
        {
            this.parts = new ArrayList<Part>(parts);
            return this;
        }
    
        /**
         * Adds an HTTP multipart part.
         * <p/>
         * <p>
         * Overriding is only supported for the purpose of calling the super implementation and changing
         * the return type, but nothing else.
         * </p>
         */
        public MultipartFormContent addPart(Part part)
        {
            parts.add(Preconditions.checkNotNull(part));
            return this;
        }
    
        /**
         * Returns the boundary string to use.
         */
        public final String getBoundary()
        {
            return getMediaType().getParameter("boundary");
        }
    
        /**
         * Sets the boundary string to use.
         * <p/>
         * <p>
         * Defaults to {@code "__END_OF_PART__"}.
         * </p>
         * <p/>
         * <p>
         * Overriding is only supported for the purpose of calling the super implementation and changing
         * the return type, but nothing else.
         * </p>
         */
        public MultipartFormContent setBoundary(String boundary)
        {
            getMediaType().setParameter("boundary", Preconditions.checkNotNull(boundary));
            return this;
        }
    
        /**
         * Single part of a multi-part request.
         * <p/>
         * <p>
         * Implementation is not thread-safe.
         * </p>
         */
        public static final class Part
        {
    
            /**
             * Name of this FormPart
             */
            private String name;
            /**
             * FileName of the File being uploaded or {@code null} for none.
             */
            private String filename;
            /**
             * HTTP header or {@code null} for none.
             */
            private HttpHeaders headers;
            /**
             * HTTP content or {@code null} for none.
             */
            private HttpContent content;
            /**
             * HTTP encoding or {@code null} for none.
             */
            private HttpEncoding encoding;
    
            public Part()
            {
                this(null, null);
            }
    
            /**
             * @param headers HTTP headers or {@code null} for none
             * @param content HTTP content or {@code null} for none
             */
            public Part(String name, HttpContent content)
            {
                setName(name);
                setContent(content);
            }
    
            /**
             * Returns the HTTP content or {@code null} for none.
             */
            public HttpContent getContent()
            {
                return content;
            }
    
            /**
             * Sets the HTTP content or {@code null} for none.
             */
            public Part setContent(HttpContent content)
            {
                this.content = content;
                if (content instanceof FileContent)
                {
                    final File file = ((FileContent) content).getFile();
                    if (file != null && file.exists())
                    {
                        setFilename(file.getName());
                    }
                }
                return this;
            }
    
            public String getName()
            {
                return name;
            }
    
            public Part setName(final String name)
            {
                this.name = name;
                return this;
            }
    
            public String getFilename()
            {
                return filename;
            }
    
            /**
             * Set the HTTP form-part filename or null for none.
             *
             * @param filename
             */
            public Part setFilename(final String filename)
            {
                this.filename = filename;
                return this;
            }
    
            /**
             * Returns the HTTP headers or {@code null} for none.
             */
            public HttpHeaders getHeaders()
            {
                return headers;
            }
    
            /**
             * Sets the HTTP headers or {@code null} for none.
             */
            public Part setHeaders(final HttpHeaders headers)
            {
                this.headers = headers;
                return this;
            }
    
            /**
             * Returns the HTTP encoding or {@code null} for none.
             */
            public HttpEncoding getEncoding()
            {
                return encoding;
            }
    
            /**
             * Sets the HTTP encoding or {@code null} for none.
             */
            public Part setEncoding(HttpEncoding encoding)
            {
                this.encoding = encoding;
                return this;
            }
        }
    }
    

    这对我有用,我正在使用 Cloudinary。

    【讨论】:

      猜你喜欢
      • 2018-04-08
      • 1970-01-01
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多