何度やっても同じ

ただの日記

BlobstoreService + slim3 でプチはまり

Blobstoreにファイルをアップロードするのといっしょにサーバにパラメータを渡す必要があったので、実現方法を二つほど考えたのですが、

  • multipartで送る
  • Blobアップロード後に呼び出されるパスにあらかじめクエリ文字列でパラメータを埋め込んでおく

どちらの方法でも渡せないのでした。いや、サーバには渡せているのだけど、どちらもslim3によって処理されないのです(前者の方法は開発環境では何故か問題ないみたい)。なので、アップロード後に呼ばれるコントローラは次のような状態です。別にこれでもいいんですけどね。。。

String id = asString("id"); // ぬるっと
String id = request.getParameter("id"); // これなら取得できる

これでは不満な場合、以下のように解決できそう。

まずこんなクラスを作ってですね。。。

public class BlobUploadedRequestHander extends RequestHandler {

  public BlobUploadedRequestHander(HttpServletRequest request) {
    super(request);
  }

  @Override
  public void handle() {
    super.handle();
    BlobstoreService blobstore = BlobstoreServiceFactory.getBlobstoreService();
    Map<String, List<BlobKey>> map = blobstore.getUploads(request);
    for (Map.Entry<String, List<BlobKey>> e : map.entrySet()) {
      request.setAttribute(e.getKey(), e.getValue());
    }
  }
}

アップロード後の処理をするコントローラを次のように。ついでに共通の親コントローラにasBlobKeyメソッドとか定義しておくと更にすっきり。

public class UploadController extends OreOreController {

  @Override
  protected RequestHandler createRequestHandler(HttpServletRequest request) {
    return new BlobUploadedRequestHander(request);
  }

  @Override
  public Navigation run() throws Exception {

    Validators v = new Validators(request);
    v.add("id", v.required(), v.longType());
    v.add("file", v.required());
    if (!v.validate()) {
      return forward("xxx.jsp");
    }

    long id = asLong("id");
    BlobKey blobKey = asBlobKey("file");

    // なんか処理
  }
}