okhttp请求头中不能含有中文Unexpected char 0x65b0 at 34 in Content-Disposition value: form-data; name="file";

使用retrofit上传附件时候文件名是中文问题
在上传附件时候,自己测试时候一直传的是相册中的图片,没有出现什么问题;当选择“新建文件.txt”这个txt时候出现如下崩溃:

Caused by: java.lang.IllegalArgumentException: Unexpected char 0x65b0 at 34 in Content-Disposition value: form-data; name="file"; filename="新建数据.txt"
        at okhttp3.Headers.checkValue(Headers.java:272)
        at okhttp3.Headers.of(Headers.java:224)
        at okhttp3.MultipartBody$Part.createFormData(MultipartBody.java:259)
        at com.coop.petitionletter.fragment.ComplainFragment.uploadAttachment(ComplainFragment.java:326)
        at com.coop.petitionletter.fragment.ComplainFragment.onActivityResult(ComplainFragment.java:470)
        at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:160)
        at android.app.Activity.dispatchActivityResult(Activity.java:7794)

排查问题,可能是中文导致的;重新创建“aa.txt”进行上传,果然没有中文可以上传成功;

RequestBody requestBody = RequestBody.create(MediaType.parse("*/*"), path);
        MultipartBody.Part upfile = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        ApiStore.createApi(ApiService.class)

进入MultipartBody的createFormData源码部分

public static Part createFormData(String name, @Nullable String filename, RequestBody body) {
      if (name == null) {
        throw new NullPointerException("name == null");
      }
      StringBuilder disposition = new StringBuilder("form-data; name=");
      appendQuotedString(disposition, name);

      if (filename != null) {
        disposition.append("; filename=");
        appendQuotedString(disposition, filename);
      }

      return create(Headers.of("Content-Disposition", disposition.toString()), body);//最终传递到了这里
    }

进入Heads.of方法

  /**
   * Returns headers for the alternating header names and values. There must be an even number of
   * arguments, and they must alternate between header names and values.
   */
  public static Headers of(String... namesAndValues) {
    if (namesAndValues == null) throw new NullPointerException("namesAndValues == null");
    if (namesAndValues.length % 2 != 0) {
      throw new IllegalArgumentException("Expected alternating header names and values");
    }

    // Make a defensive copy and clean it up.
    namesAndValues = namesAndValues.clone();
    for (int i = 0; i < namesAndValues.length; i++) {
      if (namesAndValues[i] == null) throw new IllegalArgumentException("Headers cannot be null");
      namesAndValues[i] = namesAndValues[i].trim();
    }

    // Check for malformed headers.
    for (int i = 0; i < namesAndValues.length; i += 2) {
      String name = namesAndValues[i];
      String value = namesAndValues[i + 1];
      checkName(name);//-------这里检查文件名
      checkValue(value, name);//---------检查内容
    }

    return new Headers(namesAndValues);
  }

checkName方法如下,也就是在这里报错了,发现这里有校验

  static void checkName(String name) {
    if (name == null) throw new NullPointerException("name == null");
    if (name.isEmpty()) throw new IllegalArgumentException("name is empty");
    for (int i = 0, length = name.length(); i < length; i++) {
      char c = name.charAt(i);
      if (c <= '\u0020' || c >= '\u007f') {
        throw new IllegalArgumentException(Util.format(
            "Unexpected char %#04x at %d in header name: %s", (int) c, i, name));
      }
    }
  }

解决方案:

URLEncoder.encode(file.getName(),"UTF-8");//App传递给后台时候编码
URLDecoder.decode(ss,"UTF-8");//后台接到时候进行转码

参考:
okhttp3请求头中含中文报错原因及解决方案
HTTP Header中不能传输中文

你可能感兴趣的:(Unexpected,char,checkName,android)