【问题标题】:How can I write a Multipart entity into a file when using Retrofit/OkHttp?使用 Retrofit/OkHttp 时如何将 Multipart 实体写入文件?
【发布时间】:2016-05-31 06:11:47
【问题描述】:

我正在更新最初使用 Apache HTTP 客户端构建的代码,以改用 Retrofit。我遇到问题的代码块将本地应用程序数据库的副本上传到我的服务器。此过程的一部分是使用在 POST 身份验证中发送的内容的 md5。它首先创建多部分实体,然后将其写入一个新文件,以便可以在该文件上制作 md5。

public class MyRestClient extends AsyncHttpClient {

 public void sendBackup(String secretKey, String accessId, AsyncHttpResponseHandler responseHandler){

    File file = new File(FileUtil.DATBASE_DIRECTORY_PATH + File.separator + FileUtil.DATABASE_FILE_NAME + ".db");
    MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, boundary, Charset.forName("UTF-8"));
    FileBody fileBody = new FileBody(file);
    entity.addPart("device_backup[database_dump]", fileBody);


    //creating this dummy file is crucial because for the server to authorize this file the
    //server takes the md5 of the raw_post of the request and compares it to the md5 in the header
    //this dummy file is mimicking the request.raw_post that is done on the server
    File dummyFile = new File(FileUtil.DATBASE_DIRECTORY_PATH + File.separator + "dummy.db");
    try {

      if (!dummyFile.exists()) {
        dummyFile.createNewFile();
      }

      FileOutputStream fileOutputStream = new FileOutputStream(dummyFile);
      entity.writeTo(fileOutputStream);

      fileOutputStream.flush();
      fileOutputStream.close();

    } catch (IOException e) {
      e.printStackTrace();
    }

    setAuth(DEVICE_BACKUP_EXTENSION, dummyFile, secretKey, accessId);

    super.post(MyApplication.getContext(), DEVICE_BACKUP_URL, entity, MultipartContentType, responseHandler);
  }
}

到目前为止我所拥有的:

public void backupCurrentDatabase(final Long backupId) {

    public static String boundary = "*****";
    public static final String MultipartContentType = "multipart/form-data;boundary=" + 
        boundary + "; charset=UTF-8";

    SharedPreferences prefs = getActivity().getSharedPreferences(Const.SHARE_PREF_NAME, Context.MODE_PRIVATE);
    String accessId = prefs.getString(Const.ACCESS_ID_PREF_KEY, null);
    String secretKey = prefs.getString(Const.SECRET_KEY_PREF_KEY, null);
    File file = new File(FileUtil.DATBASE_DIRECTORY_PATH + File.separator + FileUtil.DATABASE_FILE_NAME + ".db");

    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("device_backup[database_dump]", FileUtil.DATABASE_FILE_NAME + ".db",
                    RequestBody.create(MediaType.parse(MultipartContentType), file))
            .build();

    File dummyFile = new File(FileUtil.DATBASE_DIRECTORY_PATH + File.separator + "dummy.db");
    try {

      if (!dummyFile.exists()) {
        dummyFile.createNewFile();
      }

      FileOutputStream fileOutputStream = new FileOutputStream(dummyFile);
      //Write requestBody to dummyFile

      fileOutputStream.flush();
      fileOutputStream.close();

    } catch (IOException e) {
      e.printStackTrace();
    }

    SyncApi client = ServiceGenerator.createService(SyncApi.class, ServiceGenerator.DEVICE_BACKUP_EXTENSION,
            dummyFile, secretKey, accessId);
    Call<SendBackup> call = client.sendBackup(requestBody);
  }

所以我获取了相同的信息,并制作了一个可以通过 Retrofit 传递的 RequestBody。看来这应该是我写给 dummyFile 的内容。接下来是将 Multipart 写入 dummyFile 的相同代码,除了它缺少实际写入 fileOutputStream 的重要部分,因为我不知道要使用什么函数。接下来,设置 Retrofit 实例并将所有身份验证信息传递给我的服务生成器。最后拨打电话并将 requestBody 传递给 Retrofit。 (call.enqueue() 的东西没有显示)

我缺少什么来完成这项工作?使用 RequestBody 是否正确?

【问题讨论】:

    标签: android retrofit okhttp retrofit2 okhttp3


    【解决方案1】:
     /**
     * Upload picture API method.
     * This upload picture feature is only for demo purpose.
     */
    public void UploadPictureToServer()
    {
        if (file != null)
        {
            final APIParameters parameters = new APIParameters(MainActivity.this,true,false);
            Call<ResponseBody> call = parameters.GetUploadImageParameters(file);
            if (call == null)
            {
                return;
            }
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
    
                    parameters.DismissLoader();
                    GetUploadImageData(response);
                }
    
                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
    
                    parameters.DismissLoader();
                    t.printStackTrace();
                }
            });
        }
    }
    
    /**
     * Get Upload image response for parsing data
     * @param response
     */
    private void GetUploadImageData(Response<ResponseBody> response)
    {
        String MyResult = null;
        try
        {
            MyResult = CM.GetAPIResponseStatus(response.body().string(),MainActivity.this);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    
        if (MyResult == null)
        {
            return;
        }
    
        ArrayList<Model_Category> model_categoryArrayList = JSONHelper.parseUploadImageResponse(MyResult);
        if (model_categoryArrayList != null)
        {
         /*   try
            {
                CacheMemory.writeObject(MainActivity.this, "category.txt", model_categoryArrayList);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }*/
            for (int i=0;i<model_categoryArrayList.size();i++)
            {
                Log.e("Category :-->","Id : "+model_categoryArrayList.get(i).id+" Name : "+model_categoryArrayList.get(i).categoryName);
            }
        }
    }
    

    API 接口

    /**
     * If you do not need any type-specific response, you can specify return value as simply Call<ResponseBody>.
     * @param image
     * @param //name
     * @return
     */
    @Multipart
    @POST(URLS.WEB_ADD_CATEGORY)
    Call<ResponseBody> postImage(@Query(WebServicesTags.TAG_STR_APIKEY) String apiKey,@Part MultipartBody.Part image,@Part("userId") RequestBody userId,@Part("categoryName") RequestBody categoryName,@Part("deviceType") RequestBody deviceType,@Part("deviceToken") RequestBody deviceToken,@Part("accessToken") RequestBody accessToken,@Part("intUdId") RequestBody intUdId);
    

    【讨论】:

      猜你喜欢
      • 2021-12-02
      • 1970-01-01
      • 2020-05-08
      • 1970-01-01
      • 2015-09-10
      • 1970-01-01
      • 2014-08-25
      • 2015-08-26
      • 2017-02-26
      相关资源
      最近更新 更多