【问题标题】:File upload with okhttp使用 okhttp 上传文件
【发布时间】:2015-08-01 02:07:33
【问题描述】:

我正在完成这个使用 okhttp 与 web 服务通信的项目。

常规 GET 和 POST 一切正常,但我无法正确上传文件。

okhttp 文档在这些主题上非常缺乏,我在这里或任何地方找到的所有内容似乎都不适用于我的情况。

应该很简单:我必须同时发送文件和一些字符串值。但我不知道该怎么做。

根据我找到的一些示例,我首先尝试了这个:

RequestBody requestBody = new MultipartBuilder().type(MultipartBuilder.FORM)
    .addFormDataPart("group", getGroup())
    .addFormDataPart("type", getType())
    .addFormDataPart("entity", Integer.toString(getEntity()))
    .addFormDataPart("reference", Integer.toString(getReference()))
    .addPart(Headers.of("Content-Disposition", "form-data; name=\"task_file\""), RequestBody.create(MediaType.parse("image/png"), getFile()))
    .build();

它给了我一个“400 bad request”错误。

所以我从 okhttp 食谱中尝试了这个:

RequestBody requestBody = new MultipartBuilder().type(MultipartBuilder.FORM)
    .addPart(Headers.of("Content-Disposition", "form-data; name=\"group\""), RequestBody.create(null, getGroup()))
    .addPart(Headers.of("Content-Disposition", "form-data; name=\"type\""), RequestBody.create(null, getType()))
    .addPart(Headers.of("Content-Disposition", "form-data; name=\"entity\""), RequestBody.create(null, Integer.toString(getEntity())))
    .addPart(Headers.of("Content-Disposition", "form-data; name=\"reference\""), RequestBody.create(null, Integer.toString(getReference())))
    .addPart(Headers.of("Content-Disposition", "form-data; name=\"task_file\""), RequestBody.create(MediaType.parse("image/png"), getFile()))
    .build();

同样的结果。

不知道还有什么可以尝试或如何调试。

使用以下代码完成请求:

// adds the required authentication token
Request request = new Request.Builder().url(getURL()).addHeader("X-Auth-Token", getUser().getToken().toString()).post(requestBody).build();
Response response = client.newCall(request).execute();

但我很确定问题在于我如何构建请求正文。

我做错了什么?

编辑:顺便说一下,上面的“getFile()”返回一个 File 对象。其余参数都是字符串和整数。

【问题讨论】:

    标签: java android okhttp


    【解决方案1】:

    在最初的帖子之后,我找到了自己问题的答案。

    我会把它留在这里,因为它对其他人有用,因为周围有这么几个 okhttp 上传示例:

    RequestBody requestBody = new MultipartBuilder().type(MultipartBuilder.FORM)
            .addFormDataPart("group", getGroup())
            .addFormDataPart("type", getType())
            .addFormDataPart("entity", Integer.toString(getEntity()))
            .addFormDataPart("reference", Integer.toString(getReference()))
            .addFormDataPart("task_file", "file.png", RequestBody.create(MediaType.parse("image/png"), getFile()))
                                                    .build();
    

    没有理由像在食谱中那样将“addPart”与“Headers.of”等一起使用,addFormDataPart 可以解决问题。

    对于文件字段本身,它需要 3 个参数:名称、文件名,然后是文件正文。就是这样。

    【讨论】:

    • 我遇到了同样的问题...想知道为什么食谱建议将“addPart”与“Headers.of”一起使用。
    • getFile() 函数在做什么?是给图片路径的吗?
    • @JaiminModi RequestBody.create(MEDIA_TYPE_PNG, sourceFile) 其中sourceFile 是文件对象。
    • 好的,这意味着我可以传递存储在我的 sdcard 中的图像路径,或者我必须在那里传递位图?
    • 请注意 MultipartBuilder 类不再存在。
    【解决方案2】:

    我刚刚更改了addFormDataPart 而不是addPart 并最终使用以下代码解决了我的问题:

      /**
         * Upload Image
         *
         * @param memberId
         * @param sourceImageFile
         * @return
         */
        public static JSONObject uploadImage(String memberId, String sourceImageFile) {
    
            try {
                File sourceFile = new File(sourceImageFile);
    
                Log.d(TAG, "File...::::" + sourceFile + " : " + sourceFile.exists());
    
                final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
    
                RequestBody requestBody = new MultipartBuilder()
                        .type(MultipartBuilder.FORM)
                        .addFormDataPart("member_id", memberId)
                        .addFormDataPart("file", "profile.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
                        .build();
    
                Request request = new Request.Builder()
                        .url(URL_UPLOAD_IMAGE)
                        .post(requestBody)
                        .build();
    
                OkHttpClient client = new OkHttpClient();
                Response response = client.newCall(request).execute();
                return new JSONObject(response.body().string());
    
            } catch (UnknownHostException | UnsupportedEncodingException e) {
                Log.e(TAG, "Error: " + e.getLocalizedMessage());
            } catch (Exception e) {
                Log.e(TAG, "Other Error: " + e.getLocalizedMessage());
            }
            return null;
        }
    

    【讨论】:

    • 如果你用的是php,能不能给下服务器端的代码??
    • 什么是 MultipartBuilder。 shubhank 说它是 okHttp 的一部分,但是当我在我的项目中使用它时它没有解决并给我错误
    【解决方案3】:

    OKHTTP 3+ 中使用这个 AsyncTask

    SignupWithImageTask

      public class SignupWithImageTask extends AsyncTask<String, Integer, String> {
    
            ProgressDialog progressDialog;
    
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                progressDialog = new ProgressDialog(SignupActivity.this);
                progressDialog.setMessage("Please Wait....");
                progressDialog.show();
            }
    
            @Override
            protected String doInBackground(String... str) {
    
                String res = null;
                try {
    //                String ImagePath = str[0];
                    String name = str[0], email = str[1], dob = str[2], IMEI = str[3], phone = str[4], ImagePath = str[5];
    
                    File sourceFile = new File(ImagePath);
    
                    Log.d("TAG", "File...::::" + sourceFile + " : " + sourceFile.exists());
    
                    final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/*");
    
                    String filename = ImagePath.substring(ImagePath.lastIndexOf("/") + 1);
    
                    /**
                     * OKHTTP2
                     */
    //            RequestBody requestBody = new MultipartBuilder()
    //                    .type(MultipartBuilder.FORM)
    //                    .addFormDataPart("member_id", memberId)
    //                    .addFormDataPart("file", "profile.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
    //                    .build();
    
                    /**
                     * OKHTTP3
                     */
                    RequestBody requestBody = new MultipartBody.Builder()
                            .setType(MultipartBody.FORM)
                            .addFormDataPart("image", filename, RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
                            .addFormDataPart("result", "my_image")
                            .addFormDataPart("name", name)
                            .addFormDataPart("email", email)
                            .addFormDataPart("dob", dob)
                            .addFormDataPart("IMEI", IMEI)
                            .addFormDataPart("phone", phone)
                            .build();
    
                    Request request = new Request.Builder()
                            .url(BASE_URL + "signup")
                            .post(requestBody)
                            .build();
    
                    OkHttpClient client = new OkHttpClient();
                    okhttp3.Response response = client.newCall(request).execute();
                    res = response.body().string();
                    Log.e("TAG", "Response : " + res);
                    return res;
    
                } catch (UnknownHostException | UnsupportedEncodingException e) {
                    Log.e("TAG", "Error: " + e.getLocalizedMessage());
                } catch (Exception e) {
                    Log.e("TAG", "Other Error: " + e.getLocalizedMessage());
                }
    
    
                return res;
    
            }
    
            @Override
            protected void onPostExecute(String response) {
                super.onPostExecute(response);
                if (progressDialog != null)
                    progressDialog.dismiss();
    
                if (response != null) {
                    try {
    
                        JSONObject jsonObject = new JSONObject(response);
    
    
                        if (jsonObject.getString("message").equals("success")) {
    
                            JSONObject jsonObject1 = jsonObject.getJSONObject("data");
    
                            SharedPreferences settings = getSharedPreferences("preference", 0); // 0 - for private mode
                            SharedPreferences.Editor editor = settings.edit();
                            editor.putString("name", jsonObject1.getString("name"));
                            editor.putString("userid", jsonObject1.getString("id"));
                            editor.putBoolean("hasLoggedIn", true);
                            editor.apply();
    
                            new UploadContactTask().execute();
    
                            startActivity(new Intent(SignupActivity.this, MainActivity.class));
                        } else {
                            Toast.makeText(SignupActivity.this, "" + jsonObject.getString("message"), Toast.LENGTH_SHORT).show();
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else {
                    Toast.makeText(SignupActivity.this, "Something Went Wrong", Toast.LENGTH_SHORT).show();
                }
    
            }
        }
    

    【讨论】:

      【解决方案4】:

      这里是如何使用 okhttp3 上传文件。

            try {
      
                UpdateInformation("yourEmailAddress", filePath, sourceFile);
      
                } catch (IOException e) {
                              e.printStackTrace();
               }
      
          private void UploadInformation(String email, final String _filePath, final File file) throws IOException {
      
      
              runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
      
      
                  //show progress bar here
      
                  }
              });
      
      
              OkHttpClient client = new OkHttpClient.Builder()
                      .connectTimeout(60, TimeUnit.SECONDS)
                      .writeTimeout(60, TimeUnit.SECONDS)
                      .readTimeout(60, TimeUnit.SECONDS)
                      .build();
      
      
      
      
      
              String mime = getMimeType(_filePath);
      
      
              RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                      .addFormDataPart("file", file.getName(),
                              RequestBody.create(MediaType.parse(mime), file))
                      .addFormDataPart("email", email)
                      .build();
      
      
      
      
      
              okhttp3.Request request = new okhttp3.Request.Builder()
                      .url("yourEndPointURL")
                      .post(body)
                      .addHeader("authorization", "yourEndPointToken")
                      .addHeader("content-type", "application/json")
                      .build();
      
      
      
              client.newCall(request).enqueue(new Callback() {
                  @Override
                  public void onFailure(Call call, IOException e) {
                      call.cancel();
      
      
                      runOnUiThread(new Runnable() {
                          @Override
                          public void run() {
      
                          //hide progress bar here
      
                          }
                      });
      
                  }
      
                  @Override
                  public void onResponse(Call call, okhttp3.Response response) throws IOException {
      
      
                      try {
      
                          final String myResponse = response.body().string();
      
      
                          runOnUiThread(new Runnable() {
                              @Override
                              public void run() {
      
                          //hide progress bar here
      
                          //Cont from here
                          //Handle yourEndPoint Response.
      
      
      
                              }
                          });
      
      
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
      
      
                  }
      
      
      
              });
          }
      
      
      private String getMimeType(String path) {
              FileNameMap fileNameMap = URLConnection.getFileNameMap();
              String contentTypeFor = fileNameMap.getContentTypeFor(path);
              if (contentTypeFor == null)
              {
                  contentTypeFor = "application/octet-stream";
              }
              return contentTypeFor;
          }
      

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2014-06-24
        • 2014-08-08
        • 2021-01-19
        • 2020-05-08
        • 2016-06-20
        • 2016-06-29
        • 2016-02-26
        • 2014-10-11
        相关资源
        最近更新 更多