多部分 headers 似乎被忽略了

Multipart headers seem to be ignored

我有以下代码,它应该向某些服务发送 POST 请求,基本上 post 一个文件。

这个请求是multipart/form-data。它包括:

代码如下:

sendMultipartPost();

def sendMultipartPost() 
{
  def URLToGo = 'http://127.0.0.1:8080/sd/services/rest/find/';
  def httpRequest = new HTTPBuilder(URLToGo);
  def authToken = 'AR-JWT ' + 'TOKEN';

  def headers = ['Authorization' : authToken, 'Content-Type' : 'multipart/form-data; boundary=W3NByNRZZYy4ALu6xeZzvWXU3NVmYUxoRB'];  
  httpRequest.setHeaders(headers);

  def body = ["values":["Incident Number":'testSC',"Work Log Type":"General Information","Description":"File has been added TESTFile","z2AF Work Log01":'Test File title']];

  httpRequest.request(Method.POST) 
  {
      req ->

      MultipartEntity multiPartContent = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, 'W3NByNRZZYy4ALu6xeZzvWXU3NVmYUxoRB', Charset.forName("UTF-8"));

      Gson gson = new Gson(); 
      String jsonObj = gson.toJson(body);

      multiPartContent.addPart('entry', new StringBody(jsonObj, ContentType.APPLICATION_JSON));
      multiPartContent.addPart('attach-z2AF Work Log01', new ByteArrayBody(Base64.encodeBase64("let's createBase64 let's createBase64 let's createBase64 let's createBase64 let's createBase64".getBytes()), ContentType.APPLICATION_OCTET_STREAM, 'test file title'));

      req.setEntity(multiPartContent);

      response.success = { resp ->

          if (resp.statusLine.statusCode == 200) {

                    // response handling

                     }
              }

       response.failure = { resp, json ->
        result = groovy.json.JsonOutput.toJson(['state':resp.status])
          }
  }
}

但是,每当我发送请求时,似乎有一些 header 被遗漏或未指定:

The generated request's body

但是 "perfect" 请求看起来像这样:

The perfect request

现在我们可以得出以下结论 JSON 的 header:

从 base64 开始:

因此,我有两个问题:

提前致谢

Why is the header Content-Type of JSON absent whilst I actually set it?

因为您正在使用 HttpMultipartMode.BROWSER_COMPATIBLE 模式。删除它,你会得到 content-type header.

How do I specify the headers which are not present at all?

此库中的唯一方法 - 使用 FormBodyPart 包装任何 body 并添加所需的 headers.

这是您可以在 groovyconsole

中 运行 的代码示例
@Grab(group='org.apache.httpcomponents', module='httpmime', version='4.5.10')
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.content.StringBody
//import org.apache.http.entity.mime.content.ByteArrayBody
import org.apache.http.entity.mime.FormBodyPartBuilder

//form part has ability to specify additional part headers
def form(Map m){
    def p = FormBodyPartBuilder.create(m.remove('name'), m.remove('body'))
    m.each{ k,v-> p.addField(k,v.toString()) } //all other keys assume to be headers
    return p.build()
}

def json = '{"aaa":111,"bbb":222,"ccc":333}'

def multipart = MultipartEntityBuilder.create()
        .addTextBody( "foo", 'bar' ) //transfer text with default encoding
        .addTextBody( "theJson", json, ContentType.APPLICATION_JSON ) //text with content type
        .addPart(form(
                //add part with headers
                name:'TheJsonWithHdrs', 
                body:new StringBody(json.getBytes("UTF-8").encodeBase64().toString(),ContentType.APPLICATION_JSON), 
                'Content-transfer-encoding':'base64',
            ))
        .build()

//print result
def b = new ByteArrayOutputStream()
multipart.writeTo(b)
println b.toString("ASCII")

结果

--s89LGRZ8HCJ4Gimdis8AH2pXpUQyEpvalzB
Content-Disposition: form-data; name="foo"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit

bar
--s89LGRZ8HCJ4Gimdis8AH2pXpUQyEpvalzB
Content-Disposition: form-data; name="theJson"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit

{"aaa":111,"bbb":222,"ccc":333}
--s89LGRZ8HCJ4Gimdis8AH2pXpUQyEpvalzB
Content-transfer-encoding: base64
Content-Disposition: form-data; name="TheJsonWithHdrs"
Content-Type: application/json; charset=UTF-8

eyJhYWEiOjExMSwiYmJiIjoyMjIsImNjYyI6MzMzfQ==
--s89LGRZ8HCJ4Gimdis8AH2pXpUQyEpvalzB--