動画を Blobstore にアップロードできるようにする REST API を Google App Engine で作成しようとしています。私のローカル開発サーバーではすべて正常に動作しますが、GAE にデプロイすると失敗します。GAE ではビデオを保存しますが、コールバック URL を呼び出しません。代わりに、ロケーション ヘッダーがコールバック URL に設定された 302 を返します。クライアントからコールバック URL に手動でアクセスしようとしましたが、GAE は例外をスローします: java.lang.IllegalStateException: Must be called from a blob upload callback request
. Spring MVC を使用しています。
クライアント アップロード コード:
/**
* URL has been generated by going to /game/{gameId}/video
*/
private void uploadVideo(String uploadUrl) throws Exception {
HttpClient httpClient = new DefaultHttpClient();
httpClient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
HttpPost post = new HttpPost(uploadUrl);
MultipartEntity mp = new MultipartEntity();
File video = new File("src/test/resources/video.mp4");
assertTrue("Couldn't find video file.", video.exists());
mp.addPart("video", new FileBody(video));
post.setEntity(mp);
HttpResponse resp = httpClient.execute(post);
//Getting 302 here.
assertEquals("Unexpected HTTP status code.", 200, resp.getStatusLine().getStatusCode());
}
サーバーコード:
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
/**
* Create a video entity and generate an upload URL.
*/
@RequestMapping(value = "/game/{gameId}/video", method=RequestMethod.POST)
@ResponseBody
public VideoMeta createVideo(@PathVariable Long gameId, @RequestBody VideoMeta meta, Principal auth) {
//Omitted authentication and video creation logic
//Get blobstore upload URL. Callback is /video/{videoId}/blob.
String uploadUrl = blobstoreService.createUploadUrl("/video/" + video.getId() + "/blob");
//Create response
VideoMeta videoMeta = new VideoMeta();
videoMeta.setVideoId(video.getId());
videoMeta.setUploadUrl(uploadUrl);
return videoMeta;
}
/**
* This method is never called on GAE!
*/
@RequestMapping(value = "/video/{videoId}/blob", method=RequestMethod.POST)
@ResponseBody
public VideoMeta uploadVideo(@PathVariable Long videoId, HttpServletRequest req) {
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("video");
blobstoreService.getByteRange(req);
int numBlobs = blobKeys.size();
if(numBlobs != 1) {
throw new RestException(HttpServletResponse.SC_NOT_ACCEPTABLE, "You should upload exactly one blob.");
}
BlobKey blobKey = blobKeys.get(0);
//Omitted video update logic
VideoMeta videoMeta = new VideoMeta();
videoMeta.setVideoId(video.getId());
return videoMeta;
}