Tom是个码农 2023-04-14 17:59 采纳率: 33.3%
浏览 10
已结题

使用Retrofit上传图片文件图片后台解析不出来 是哪里有问题吗

img

img

img

提交之后就是解析不出来 不知道是因为什么 有没有人做过这种的帮忙看一下

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-04-16 00:40
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:
    • 关于该问题,我找了一篇非常好的博客,你可以看看是否有帮助,链接:【Demo见真章】将安卓的Retrofit移植到鸿蒙系统上,在鸿蒙系统上实现一套网络请求框架
    • 除此之外, 这篇博客: Retrofit源码解析中的 方法注解的解析 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

      RequestFactory.Builder::parseMethodAnnotation方法:

          private void parseMethodAnnotation(Annotation annotation) {
            if (annotation instanceof DELETE) {
              parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
            } else if (annotation instanceof GET) {
              parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
            } else if (annotation instanceof HEAD) {
              parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
            } else if (annotation instanceof PATCH) {
              parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
            } else if (annotation instanceof POST) {
              parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
            } else if (annotation instanceof PUT) {
              parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
            } else if (annotation instanceof OPTIONS) {
              parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
            } else if (annotation instanceof HTTP) {
              HTTP http = (HTTP) annotation;
              parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
            } else if (annotation instanceof retrofit2.http.Headers) {
              String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
              if (headersToParse.length == 0) {
                throw methodError(method, "@Headers annotation is empty.");
              }
              headers = parseHeaders(headersToParse);
            } else if (annotation instanceof Multipart) {
              if (isFormEncoded) {
                throw methodError(method, "Only one encoding annotation is allowed.");
              }
              isMultipart = true;
            } else if (annotation instanceof FormUrlEncoded) {
              if (isMultipart) {
                throw methodError(method, "Only one encoding annotation is allowed.");
              }
              isFormEncoded = true;
            }
          }
      

      这里对方法注解的处理方式主要可以分为三类:

      1. GETPOST等请求方法:调用RequestFactory.Builder::parseHttpMethodAndPath方法进行处理
      2. Headers的注解:调用RequestFactory.Builder::parseHeaders方法进行处理
      3. MultipartFormUrlEncoded注解:主要是在标记变量中进行记录

      我们看下第12步是如何处理的。

      GETPOST等请求方法的注解解析,使用RequestFactory.Builder::parseHttpMethodAndPath

      private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
          // 1.若已设置过httpMethod,则抛出异常
          if (this.httpMethod != null) {
              throw methodError(
                  method,
                  "Only one HTTP method is allowed. Found: %s and %s.",
                  this.httpMethod,
                  httpMethod);
          }
          // 记录 请求方法 及 是否有请求体
          this.httpMethod = httpMethod;
          this.hasBody = hasBody;
      
          // 若请求方法的注解(如GET)里面没有写值,则结束
          if (value.isEmpty()) {
              return;
          }
      
          // Get the relative URL path and existing query string, if present.
          // 2.判断请求方法的注解中的值是否合理,不合理则抛出异常
          int question = value.indexOf('?');
          if (question != -1 && question < value.length() - 1) {
              // Ensure the query string does not have any named parameters.
              String queryParams = value.substring(question + 1);
              // 使用正则表达式匹配
              Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
              if (queryParamMatcher.find()) {
                  throw methodError(
                      method,
                      "URL query string \"%s\" must not have replace block. "
                      + "For dynamic query parameters use @Query.",
                      queryParams);
              }
          }
      
          // 3.记录相对Url;解析并记录注解中的占位符(parsePathParameters方法内部使用了正则表达式)
          this.relativeUrl = value;
          this.relativeUrlParamNames = parsePathParameters(value);
      }
      

      该方法主要做了下面的几件事情:

      1. 记录 请求方法 及 是否有请求体
      2. 判断请求方法的注解中的值是否合理,不合理则抛出异常
      3. 记录相对Url,解析并记录注解中的占位符

      我们以GET请求方法注解为例,第2步主要是防止GET的出现类似"users?sortby={sortby}"这种值,它希望我们动态设置的参数使用@Query注解来实现,举一个例子:

          @GET("/banner")
          fun getBanners(@Query("type") type: Int): Call<BannerJson>
      

      而不是

          @GET("/banner?type={type}")
          fun getBanners(@Path("type") type: Int): Call<BannerJson>
      

      3步,例如我们的请求方法为

      interface IUser {
          @GET("/users/{nickname}")
          fun getUser(@Path("nickname") nickname: String): Call<User>
      }
      

      那么计算后的值为

      // 相对url
      this.relativeUrl = "/users/{nickname}" 
      // 也就是{}包裹的值,如果有多个{},那么Set<String>会有多个值
      this.relativeUrlParamNames = 包含"nickname"的Set<String> 
      

      Headers注解的解析,使用RequestFactory.Builder::parseHeaders方法:

          private Headers parseHeaders(String[] headers) {
            // 这是okhttp3的Headers.Builder  
            Headers.Builder builder = new Headers.Builder();
            // 遍历传入的headers
            for (String header : headers) {
              int colon = header.indexOf(':');
              if (colon == -1 || colon == 0 || colon == header.length() - 1) {
                throw methodError(
                    method, "@Headers value must be in the form \"Name: Value\". Found: \"%s\"", header);
              }
              // 获取Header名和Header值  
              String headerName = header.substring(0, colon);
              String headerValue = header.substring(colon + 1).trim();
              // 如果Header是"Content-Type",则会进行一些特殊处理
              if ("Content-Type".equalsIgnoreCase(headerName)) {
                try {
                  contentType = MediaType.get(headerValue);
                } catch (IllegalArgumentException e) {
                  throw methodError(method, e, "Malformed content type: %s", headerValue);
                }
              } else {
                // 将Header添加到builder中  
                builder.add(headerName, headerValue);
              }
            }
            // 返回okhttp3.Headers  
            return builder.build();
          }
      

      该方法主要做的事情:将传入的字符串数组headers,构造为okhttp3.Headers并返回,对于Content-Type类型的Header,会进行一些特殊的处理。


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月17日
  • 创建了问题 4月14日

悬赏问题

  • ¥15 Pyqt 如何正确的关掉Qthread,并且释放其中的锁?
  • ¥30 网站服务器通过node.js部署了一个项目!前端访问失败
  • ¥15 WPS访问权限不足怎么解决
  • ¥15 java幂等控制问题
  • ¥15 海湾GST-DJ-N500
  • ¥15 氧化掩蔽层与注入条件关系
  • ¥15 Django DRF 如何反序列化得到Python对象类型数据
  • ¥15 多数据源与Hystrix的冲突
  • ¥15 如何在线硕士了解,广告太多,希望有真实接触过的人回答下?(标签-学习|关键词-在线硕士)
  • ¥15 zabbix6.4与frp如何进行联动