2

I'm trying to create a REST API on Google App Engine that allows uploading videos to Blobstore. Everything works fine on my local development server, but fails when deployed to GAE. On GAE it stores the video, but does not call my callback URL. Instead it returns a 302 with the location header set to my callback URL. I tried manually visiting the callback URL from my client, but GAE then throws an exception: java.lang.IllegalStateException: Must be called from a blob upload callback request. I'm using Spring MVC.

Client Upload Code:

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

Server Code:

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;
}
dsargeant
  • 21
  • 2
  • +1. Did you ever figured out the problem? I am dealing with a similar issue. Ref. http://stackoverflow.com/questions/16276769/combining-blob-servlet-with-endpoint-api and also http://stackoverflow.com/questions/16257895/convert-servlet-schema-to-app-engine-endpoint-schema. – learner Apr 30 '13 at 01:55

0 Answers0