You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将OkHttpClient转换为Retrofit 2:上传文件遇403 Forbidden问题排查

Troubleshooting Retrofit 2 FORBIDDEN Error for Byte Array File Uploads

Alright, let's break down why your Retrofit 2 setup is hitting a FORBIDDEN error when your original code worked perfectly. Since the API accepts a byte array for text file uploads, here are the key areas to check, with actionable fixes:

  • Mismatched Request Headers
    FORBIDDEN errors often boil down to missing or incorrect headers. Double-check that your Retrofit implementation includes exactly the same headers as your working Part 1 code—things like Authorization tokens, Content-Type, or custom API keys are easy to miss.

    For example, if your API expects application/octet-stream for byte array uploads and a Bearer token, your Retrofit interface should look like this:

    interface FileUploadService {
        @Headers("Content-Type: application/octet-stream")
        @POST("your-upload-endpoint")
        suspend fun uploadTextFile(
            @Header("Authorization") authToken: String,
            @Body fileBytes: ByteArray
        ): Response<UploadResult>
    }
    

    Pro tip: Compare the full header list from your working code (use tools like OkHttp logging) to what Retrofit is sending—even a typo in a header name can trigger 403.

  • Incorrect RequestBody Handling
    While Retrofit can automatically convert a ByteArray to a request body, sometimes the API expects a specific RequestBody configuration that your original code used. If your Part 1 code explicitly built a RequestBody with a media type, replicate that in Retrofit:

    // Build the request body exactly like your Part 1 code
    val mediaType = MediaType.parse("application/octet-stream")
    val requestBody = RequestBody.create(mediaType, fileBytes)
    
    // Update your Retrofit interface to accept RequestBody instead of ByteArray
    interface FileUploadService {
        @POST("your-upload-endpoint")
        suspend fun uploadTextFile(
            @Header("Authorization") authToken: String,
            @Body requestBody: RequestBody
        ): Response<UploadResult>
    }
    
  • Authentication Token Issues
    This is the most common culprit for 403s. Verify:

    • Your token is not expired (check its validity against the API's auth rules)
    • You're using the correct format (e.g., don't forget the Bearer prefix if required)
    • The token is being added to every Retrofit request. If your Part 1 code used an OkHttp interceptor to inject tokens, make sure your Retrofit OkHttpClient uses the same interceptor:
      val okHttpClient = OkHttpClient.Builder()
          .addInterceptor { chain ->
              val originalRequest = chain.request()
              val authenticatedRequest = originalRequest.newBuilder()
                  .header("Authorization", "Bearer ${yourValidToken}")
                  .build()
              chain.proceed(authenticatedRequest)
          }
          .build()
      
      val retrofit = Retrofit.Builder()
          .baseUrl(API_BASE_URL)
          .client(okHttpClient)
          .addConverterFactory(GsonConverterFactory.create())
          .build()
      
  • Base URL/Endpoint Path Discrepancies
    A tiny mismatch in your base URL or endpoint path can send requests to the wrong endpoint, which might return 403 due to permissions. For example:

    • If your Part 1 code uses https://api.example.com/v1/upload, ensure Retrofit's base URL is https://api.example.com/v1/ and the endpoint is @POST("upload") (not @POST("/upload"), which would drop the /v1 segment).

    Use OkHttp's logging interceptor to inspect the full request URL and confirm it matches your working code:

    val loggingInterceptor = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY // Logs headers, body, and URL
    }
    
    val okHttpClient = OkHttpClient.Builder()
        .addInterceptor(loggingInterceptor)
        .build()
    
  • Mismatched Byte Array Content
    Even if you're sending a byte array, differences in how you read the text file can change the content. For example, if your Part 1 code reads the file with UTF-8 encoding, ensure Retrofit uses the same method:

    // Read the text file exactly like your Part 1 code
    val file = File("path/to/your/textfile.txt")
    val fileBytes = file.readText(Charsets.UTF_8).toByteArray(Charsets.UTF_8)
    

    Compare the byte array length or a sample of the bytes between your two implementations to rule out content differences.

  • OkHttpClient Configuration Gaps
    If your Part 1 code uses custom OkHttp settings (like timeouts, SSL certificates, or proxies), your Retrofit client must mirror those. For example, if the API requires a specific SSL certificate pinning setup, missing that in Retrofit can lead to a 403.

内容的提问来源于stack exchange,提问作者user1154390

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:20:48