【问题标题】:Post multipart form with google-http-java-client使用 google-http-java-client 发布多部分表单
【发布时间】:2014-05-24 23:07:59
【问题描述】:

从 google-http-java-client* 文档中不清楚您将如何发布具有文件字段的表单。

例如,我正在尝试使用 Google Cloud Print API 打印文档:

HttpRequestFactory httpRequestFactory = getHttpRequestFactory();

Map<String, Object> parameters = Maps.newHashMap();
parameters.put("printerId", printRequest.getPrinterId());
parameters.put("title", printRequest.getTitle());
parameters.put("contentType", printRequest.getContentType());
parameters.put("ticket", new Gson().toJson(printRequest.getOptions()));

MultipartContent content = new MultipartContent();
content.addPart(new MultipartContent.Part(new UrlEncodedContent(parameters)));
content.addPart(new MultipartContent.Part(
        new FileContent(printRequest.getContentType(), printRequest.getFile())));

try {
    HttpResponse response = httpRequestFactory.buildPostRequest(
            SubmitUrl, content).execute();
    System.out.println(IOUtils.toString(response.getContent()));
} catch (IOException e) {
    String message = String.format();
    System.out.println("Error submitting print job: " + e.getMessage());
}

不幸的是,这不起作用。 API 返回错误“此请求所需的打印机 ID”。在我看来,请求的格式不正确。

我做错了什么?

* 我专门使用 google-http-java-client,因为它为我处理 OAuth 令牌等的自动刷新。请不要回复涉及使用其他 HTTP 客户端的解决方案。

【问题讨论】:

    标签: java google-api google-http-client


    【解决方案1】:

    看来我误解了如何将表单字段添加到多部分消息中。工作代码现在看起来像这样

    HttpRequestFactory httpRequestFactory = getHttpRequestFactory(username);
    
    Map<String, String> parameters = Maps.newHashMap();
    parameters.put("printerid", printRequest.getPrinterId());
    parameters.put("title", printRequest.getTitle());
    parameters.put("contentType", printRequest.getContentType());
    
    // Map print options into CJT structure
    Map<String, Object> options = Maps.newHashMap();
    options.put("version", "1.0");
    options.put("print", printRequest.getOptions());
    parameters.put("ticket", new Gson().toJson(options));
    
    // Add parameters
    MultipartContent content = new MultipartContent().setMediaType(
            new HttpMediaType("multipart/form-data")
                    .setParameter("boundary", "__END_OF_PART__"));
    for (String name : parameters.keySet()) {
        MultipartContent.Part part = new MultipartContent.Part(
                new ByteArrayContent(null, parameters.get(name).getBytes()));
        part.setHeaders(new HttpHeaders().set(
                "Content-Disposition", String.format("form-data; name=\"%s\"", name)));
        content.addPart(part);
    }
    
    // Add file
    FileContent fileContent = new FileContent(
            printRequest.getContentType(), printRequest.getFile());
    MultipartContent.Part part = new MultipartContent.Part(fileContent);
    part.setHeaders(new HttpHeaders().set(
            "Content-Disposition", 
            String.format("form-data; name=\"content\"; filename=\"%s\"", printRequest.getFile().getName())));
    content.addPart(part);
    
    try {
        HttpResponse response = httpRequestFactory.buildPostRequest(
                SubmitUrl, content).execute();
        System.out.println(IOUtils.toString(response.getContent()));
    } catch (IOException e) {
        ...
    }
    

    上面最重要的部分是覆盖默认的 HttpMediaType 以指定“multipart/form-data”,并将每个字段添加为自己的部分,并使用“Content-Disposition”标头来指定表单字段名称。

    【讨论】:

    • “printRequest.getContentType()”代码段中有什么内容?
    • 哇,您会认为构建多部分请求会比这更容易一些!但是谢谢,它对我有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 2012-10-29
    • 1970-01-01
    • 2014-08-06
    相关资源
    最近更新 更多