// save json value
 // {
 //    "size":filesize,
 //    "offset":lastSuccessOffset,
 //    "modify_time": lastFileModifyTime,
 //    "contexts": contexts
 // }
 private void record(int offset) {
   if (config.recorder == null || offset == 0) {
     return;
   }
   String data =
       format(
           Locale.ENGLISH,
           "{\"size\":%d,\"offset\":%d, \"modify_time\":%d, \"contexts\":[%s]}",
           size,
           offset,
           modifyTime,
           StringUtils.jsonJoin(contexts));
   config.recorder.set(recorderKey, data.getBytes());
 }
  private void makeFile(URI uri, CompletionHandler _completionHandler, UpCancellationSignal c) {
    String mime =
        format(
            Locale.ENGLISH,
            "/mimeType/%s/fname/%s",
            UrlSafeBase64.encodeToString(options.mimeType),
            UrlSafeBase64.encodeToString(f.getName()));

    String keyStr = "";
    if (key != null) {
      keyStr = format("/key/%s", UrlSafeBase64.encodeToString(key));
    }

    String paramStr = "";
    if (options.params.size() != 0) {
      String str[] = new String[options.params.size()];
      int j = 0;
      for (Map.Entry<String, String> i : options.params.entrySet()) {
        str[j++] =
            format(Locale.ENGLISH, "%s/%s", i.getKey(), UrlSafeBase64.encodeToString(i.getValue()));
      }
      paramStr = "/" + StringUtils.join(str, "/");
    }
    String path = format(Locale.ENGLISH, "/mkfile/%d%s%s%s", size, mime, keyStr, paramStr);
    URI address = uri;
    try {
      address = new URI(uri.getScheme(), uri.getHost(), path, null);
    } catch (URISyntaxException e) {
      e.printStackTrace();
    }

    String bodyStr = StringUtils.join(contexts, ",");
    byte[] data = bodyStr.getBytes();

    post(address, data, 0, data.length, null, _completionHandler, c);
  }