使用Retrofit / OkHttp时,如何将Multipart实体写入文件?

时间:2016-02-18 20:59:25

标签: android retrofit okhttp retrofit2 okhttp3

我正在更新最初使用Apache HTTP Client构建的代码,而不是使用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甚至是正确的使用方式吗?

1 个答案:

答案 0 :(得分:0)

 /**
 * 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);