java.lang.IllegalArgumentException: Unexpected char 0x5a46 at 35 in Content-Disposition value: f

java.lang.IllegalArgumentException: Unexpected char 0x5a46 at 35 in Content-Disposition value: form-data; name=“files”; filename=“婆婆說.mp3”

問題描述

使用Retrofit +okhttp上傳文件時,當文件名稱含有中文字符時,如下錯誤

 java.lang.IllegalArgumentException: Unexpected char 0x5a46 at 35 in Content-Disposition value: form-data; name="files"; filename="婆婆說.mp3"
        at okhttp3.Headers.checkValue(Headers.java:272)
        at okhttp3.Headers.of(Headers.java:224)
        at okhttp3.MultipartBody$Part.createFormData(MultipartBody.java:259)
        at common.myh.com.common.network.RequestBodyUtils.prepareFilePartForCall(RequestBodyUtils.java:69)
        at com.geotmt.collection.net.ApiRequest.getMulPartFileListForCall(ApiRequest.java:909)
        at com.geotmt.collection.net.ApiRequest.addPhoneRecord(ApiRequest.java:865)

在這裏插入圖片描述

原因分析

如圖報錯處
在這裏插入圖片描述

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);
      }
		/**
		 * 最後掉用 Headers.of方法
		 */
      return create(Headers.of("Content-Disposition", disposition.toString()), body);
    }
繼續看Headers的of方法源碼
  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];
      //檢查  name  注意拋出的異常是此處拋出的
      checkName(name);
      //檢查 value
      checkValue(value, name);
    }

    return new Headers(namesAndValues);
  }
chekName()方法源碼校驗文件的名字
  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));
      }
    }
  }

解決辦法

方案一不完美,直接try catch

這種方案本質上沒解決問題, 不是一個好的方案
在這裏插入圖片描述

方案二 將文件名進行規範,想辦法去掉中文

有很多辦法如通過 文件名的md5值進行或者通過 URLEncoder進行編碼, 到了服務器在進行解碼等

 URLEncoder.encode(file.getName(), "UTF-8")

在這裏插入圖片描述

發佈了41 篇原創文章 · 獲贊 238 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章