HttpClient发送附件post提交form表单非法请求,上传文件各个参数的作用

需要对接第三方接口,他们的接口是这样的,需要以form表单的形式传个文件。 

但是通过httpclient内置的方法请求,一直返回非法请求。我还特地去下载了fiddler来跟踪本机发出的请求,看到底是啥样的,哪里错了,fiddler跟踪结果如下:

解决方案:把附件的content-type传对!

这里的content-type是文件对应的mineType类型,关于每个文件对应的mineType类型可以去网上搜一下。mineType格式是:单词a/单词b

POST http://127.0.0.1/111/111 HTTP/1.1
Content-Type: multipart/form-data; boundary=f922d808-8f72-46e0-9922-921bc25e5853
Content-Length: 39530
Host: 127.0.0.1
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.14.4

--f922d808-8f72-46e0-9922-921bc25e5853
Content-Disposition: form-data; name="file"; filename="1.wav"
Content-Type: file/*
Content-Length: 39336

内容省略。。。                                        
--f922d808-8f72-46e0-9922-921bc25e5853--


为了搞清楚是为什么,我特地去学习了http协议。

http协议:让不同主机之间建立通信,类似寄信,需要有邮编、地址、寄信人才能送到指定位置。

请求分为3部分

1-请求行

    请求方法+请求路径+协议版本【换行】
    请求方法:Get、Post、Head(只需要返回头部内容)、Put、Trace(追踪最后发出的请求)、Options(看有哪些方法可以用)

2-请求头
    key:value
    ....

    【空行】--标志请求头的结束,无论是否有请求主体都需要。

3-请求主体

    请求主体有内容时,需要在请求头中添加Content-length的值,即请求主体的长度。解析时根据这个长度读取请求主体的内容。

    以post方式提交,还需要在请求头中添加Content-type的值。是json还是from表单,等等。
    
    像上文中,content-type是multipartFile的,带有boundary,说明要上传附件。附件没法用key-value的形式标准,所以用boundary,表示分隔标志。两个横杠加上boundary,表示附件开始,如果后面再加两个横杠表示结束。

响应也分为三部分

1-响应行

    协议+状态码+文字描述
    状态码:
        301/302 永久、暂时重定向
        304 Not Modify
        307 重定向保持原来的请求数据

2-响应头
    key:value
    【空行】

3-主体信息


学完之后回顾,感觉本机发出的请求头依然没什么大毛病,于是去搜索,http请求附件的报文格式,发现人家的content-type怎么画风这么清新,在某篇文章里看到,MIME类型这个词,才去搜索了一下,我要传的文件,对应的类型。

 

 

 最终我改了正确的类型,成功调通接口。但在此之前,其实还有一个问题。

我们是用httpclient里面的RequestBody来构建请求的,构建这个对象有几种方法。

  1. 用第一个方法,前端传一个文件过来,后端用MultipartFile类型接收,然后这个对象直接调用getBytes方法,将数组传到这个方法里,即使最后改对了这个contentType,依然是非法请求。
  2. 用第二个方法,前端传一个路径过来,后端创建一个File类型的对象,直接把这个file对象传入构造方法,改对了content-type以后,就成功调通了。

这两者的区别,道行浅,看不出来。

 /** 通过传一个byte数组来构建 */
 public static RequestBody create(final @Nullable MediaType contentType, final byte[] content) {
    return create(contentType, content, 0, content.length);
  }

  /** 通过传一个file对象构建 */
  public static RequestBody create(final @Nullable MediaType contentType, final File file) {
    if (file == null) throw new NullPointerException("file == null");

    return new RequestBody() {
      @Override public @Nullable MediaType contentType() {
        return contentType;
      }

      @Override public long contentLength() {
        return file.length();
      }

      @Override public void writeTo(BufferedSink sink) throws IOException {
        try (Source source = Okio.source(file)) {
          sink.writeAll(source);
        }
      }
    };
  } 

// 成功构造实例
RequestBody requestBody = RequestBody.create(MediaType.parse("audio/x-wav"),file); 

 

发送POST请求并携带表单元素,可以使用HttpClientHttpPost和UrlEncodedFormEntity类。示例代码如下: ```java import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; import org.apache.http.NameValuePair; import java.util.ArrayList; import java.util.List; public class HttpClientPostExample { public static void main(String[] args) throws Exception { String url = "http://example.com/api/create-user"; HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost postRequest = new HttpPost(url); // Add form parameters List<NameValuePair> urlParameters = new ArrayList<>(); urlParameters.add(new BasicNameValuePair("username", "john")); urlParameters.add(new BasicNameValuePair("password", "password123")); urlParameters.add(new BasicNameValuePair("email", "john@example.com")); postRequest.setEntity(new UrlEncodedFormEntity(urlParameters)); // Send POST request HttpResponse response = httpClient.execute(postRequest); // Print response System.out.println("Response Code : " + response.getStatusLine().getStatusCode()); } } ``` 在上面的示例代码中,我们创建了一个HttpPost对象,并将要提交的表单元素添加到UrlEncodedFormEntity中。最后,我们使用HttpClient的execute方法发送POST请求,并获取响应。注意,在实际代码中,我们需要抛出异常或使用try-catch语句来处理异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值