【问题标题】:Java POST multipart/form-data containing json and bz2 compressed file partsJava POST multipart/form-data 包含 json 和 bz2 压缩文件部分
【发布时间】:2015-01-22 20:33:39
【问题描述】:

所以我遇到了一个问题,我需要通过 java 应用程序发布 bzip2 文件。我在做多部分帖子或使用常规文件时没有问题(请参阅位于http://zewaren.net/site/?q=node/123 的第三个示例)

但是,上面的示例假设您将文件内容作为字符串发送,而我只是发送压缩内容(字节数组)。

    public void postSegments(HttpsURLConnection connection, File segment) throws UnsupportedEncodingException, IOException {
    PrintWriter OutputStream = null;
    try {
        OutputStream = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"), true);

        OutputStream.append(BOUNDARY_SPLIT).append(BOUNDARY).append("\r\n");
        OutputStream.append("Content-Disposition: form-data; name=\"").append("metadata").append("\"").append("\r\n");
        OutputStream.append("Content-Type: ").append("application/json; charset=UTF-8").append("\r\n").append("\r\n");
        OutputStream.append(META_JSON).append("\r\n");

        OutputStream.append(BOUNDARY_SPLIT).append(BOUNDARY).append("\r\n");
        OutputStream.append("Content-Disposition: form-data; name=\"data\"; filename=\"NAME\"").append("\r\n");
        OutputStream.append("Content-Type: ").append("application/octet-stream; charset=UTF-8").append("\r\n").append("\r\n");
        OutputStream.append(fileService.readFile(segment));
        OutputStream.append(BOUNDARY_SPLIT).append(BOUNDARY).append(BOUNDARY_SPLIT).append("\r\n");
    }
    finally {
        if (OutputStream != null) {
          OutputStream.close();
        }
    }

在上面的代码中,我在尝试使用通用文件扫描器读取分段文件时遇到错误(由于分段是 bzip2 文件,所以它不起作用)

我一直在寻找一个好的包装库来轻松处理发送这些处理大型/压缩文件的多部分请求,但我还没有成功。

提前谢谢大家。

【问题讨论】:

    标签: java post multipartform-data bzip2 httpsurlconnection


    【解决方案1】:

    所以我没有成功使用 httpsUrlConnection 发布文件。我找不到原因,我认为这是我声明的标题有问题。

    不过,我确实设法使用 Jersey 以及 apache 组件编写了一些基本的处理程序。

    jersey 客户端在 Oauth 中有自己的构建,而 apache 客户端使用 oauth-signpost 插件。

    注意:这些示例可以发布由文件和 json 组成的 multipart/form-data。其他输入将相当容易实现。它还使用 Oauth,而不是 Oauth2,它需要不同的库并且处理方式大不相同(即令牌刷新)

    下面是 Jersey 的实现。我不建议在大文件上使用它,因为您会将整个文件存储在内存中...您可以将其分成块并发送,但我没有这样做,因为我发现 apache 版本更适合我的需要。无论如何,这是代码:

    import java.io.ByteArrayInputStream;
    import java.io.File;
    
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.ext.Providers;
    
    import org.apache.log4j.Logger;
    
    import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.ClientResponse;
    import com.sun.jersey.api.client.WebResource;
    import com.sun.jersey.api.client.config.ClientConfig;
    import com.sun.jersey.api.client.config.DefaultClientConfig;
    import com.sun.jersey.core.header.FormDataContentDisposition;
    import com.sun.jersey.multipart.FormDataBodyPart;
    import com.sun.jersey.multipart.FormDataMultiPart;
    import com.sun.jersey.multipart.impl.MultiPartWriter;
    import com.sun.jersey.oauth.client.OAuthClientFilter;
    import com.sun.jersey.oauth.signature.OAuthParameters;
    import com.sun.jersey.oauth.signature.OAuthSecrets;
    
    public class OauthRequestJersey {
    
    private static final Logger log = Logger.getLogger(OauthRequestJersey.class);
    
    private Client client = null;
    
    private FileServiceUtil fileService = new FileServiceUtil();
    
    private FormDataMultiPart multiPart;
    
    private WebResource resource;
    
    /*
     * Oauth Request Wrapper constructor
     */
    public OauthRequestJersey(String url, String oAuthConsumerKey, String oAuthConsumerSecret){
        init();
        Providers providers = this.client.getProviders();
        OAuthSecrets secrets = new OAuthSecrets().consumerSecret(oAuthConsumerSecret);
        OAuthParameters params = new OAuthParameters().consumerKey(oAuthConsumerKey).signatureMethod("HMAC-SHA1");
        OAuthClientFilter filter = new OAuthClientFilter(providers,params,secrets);
    
        resource = client.resource(url);
        resource.addFilter(filter);
    }
    
    private void init(){
        ClientConfig config = new DefaultClientConfig();
        config.getClasses().add(MultiPartWriter.class);
        multiPart = new FormDataMultiPart();
        client = com.sun.jersey.api.client.Client.create(config);       
    }
    
    public void addJsonPart(String name, String json){
        multiPart.field(name, json, MediaType.APPLICATION_JSON_TYPE);
    }
    
    public void addFilePart(String name, File file){
        byte[] data = fileService.fileToByteArray(file);
        FormDataBodyPart fdbp = new FormDataBodyPart(
                FormDataContentDisposition.name(name)
                        .fileName(file.getName()).build(),
                         new ByteArrayInputStream(data),
                         MediaType.APPLICATION_OCTET_STREAM_TYPE);
    
        multiPart.bodyPart(fdbp);
    }
    
    public ClientResponse finish(){
        ClientResponse response = null;
        response =  resource.type(MediaType.MULTIPART_FORM_DATA)
                .post(ClientResponse.class,multiPart);
        log.debug("Response for the call " + response);
        log.debug("Response for the call status " + response.getStatus());
        return response;
    }
    
    }
    

    球衣的Maven:

        <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-multipart</artifactId>
        <version>1.18.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.18.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey.oauth</groupId>
        <artifactId>oauth-signature</artifactId>
        <version>1.1.1-ea</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey.oauth</groupId>
        <artifactId>oauth-client</artifactId>
        <version>1.1.1-ea</version>
    </dependency>
    

    下面是我的 apache 实现。这是我的首选方法,因为它自己处理文件流并抽象标题,而不必自己手动制作它们!您会注意到我还添加了一些逻辑来处理获取请求。

    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import oauth.signpost.OAuthConsumer;
    import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
    import oauth.signpost.exception.OAuthCommunicationException;
    import oauth.signpost.exception.OAuthExpectationFailedException;
    import oauth.signpost.exception.OAuthMessageSignerException;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.ResponseHandler;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.mime.MultipartEntityBuilder;
    import org.apache.http.impl.client.BasicResponseHandler;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    
    import org.apache.log4j.Logger;
    
    public class OauthRequestApache {
    private static final Logger log = Logger.getLogger(OauthRequestApache.class);
    
    private static CloseableHttpClient client;
    
    private static boolean isPost;
    
    private static HttpPost postRequest;
    
    private static HttpGet getRequest;
    
    private static MultipartEntityBuilder builder;
    
    public OauthRequestApache(String requestURL, String consumerKey, String consumerSecret, boolean post) throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException{
        isPost = post;
        OAuthConsumer consumer = new CommonsHttpOAuthConsumer(consumerKey,consumerSecret);
    
        if(isPost){
            postRequest = new HttpPost(requestURL);
            builder = MultipartEntityBuilder.create();
            consumer.sign(postRequest);
        }else{
            getRequest = new HttpGet(requestURL);
            consumer.sign(getRequest);
        }
        client = HttpClients.createDefault();
    }
    
    public void addJsonPart(String name, String value){
        builder.addTextBody(name, value, ContentType.APPLICATION_JSON);
    }
    
    public void addFilePart(String name, File file){
        builder.addBinaryBody(name, file);
    }
    
    public List<String> finish() throws ClientProtocolException, IOException{
        HttpResponse response;
        List<String> status = new ArrayList<String>();
        ResponseHandler<String> handler = new BasicResponseHandler();
        if(isPost){
            HttpEntity multipart = builder.build();
            postRequest.setEntity(multipart);
             response = client.execute(postRequest);
        }else{
            response = client.execute(getRequest);
        }
        String body = handler.handleResponse(response);
        status.add(Integer.toString(response.getStatusLine().getStatusCode()));
        status.add(body);
        client.close(); 
        return status;
    }
    }
    

    Apache 的 Maven

        <dependency>
        <groupId>oauth.signpost</groupId>
        <artifactId>signpost-core</artifactId>
    </dependency>
    <dependency>
        <groupId>oauth.signpost</groupId>
        <artifactId>signpost-commonshttp4</artifactId>
        <version>1.2.1.1</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-compress</artifactId>
        <version>1.9</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpcore</artifactId>
        <version>4.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.3.6</version>
    </dependency>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-30
      • 2015-09-19
      • 2015-12-20
      • 2018-11-19
      • 1970-01-01
      • 2011-11-19
      相关资源
      最近更新 更多