Question

I am trying to upload a video to YouTube using the Java API like this:

    private Video uploadVideo(final YouTube youtube, final Video video, final InputStreamContent mediaContent)
            throws IOException {
        YouTube.Videos.Insert videoInsert = youtube.videos().insert("snippet,statistics,status", video, mediaContent);

        MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();
        uploader.setDirectUploadEnabled(false);
        uploader.setProgressListener(progressListener);
        return videoInsert.execute();
    }
}

I have a slow and instable internet connection and it would be really helpful if I could get resumable uploads to work. The documentation here and here seem to suggest to me that the "setDirectUploadEnabled(false)" should completely do the trick. Well... obviously it does not.

If my internet connection is interrupted an IOException is thrown and there is no automatic upload resume.

How can I resume an upload?

Was it helpful?

Solution

The documentation seems to lag behind the actual implementation. For luck it is open source and you can simply read the source code to find the solution. This is about version 1.16-rc:

If an IOException occurs during uploading, the com.google.api.client.googleapis.media.MediaUploadErrorHandler is used to handle the exception. This handler also takes care of resuming an upload, but it only does so if yet another exception handler registered at the HTTP-Request successfully handles the IOException. This precondition may change in the future as a comment in the current version indicates:

// TODO(peleyal): figure out what is best practice - call serverErrorCallback only if I/O
// exception was handled, or call it regardless

Since the default io exception handler is null one must explicitly be set. This can be done when building the YouTube-Object:

The example source code here initializes the YouTube object like this:

youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(
          "youtube-cmdline-uploadvideo-sample").build();

To get this example to work, modify the line to read:

youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, new HttpRequestInitializer() {          
  @Override
  public void initialize(HttpRequest request) throws IOException {
    credential.initialize(request);
    request.setIOExceptionHandler(new HttpBackOffIOExceptionHandler(new ExponentialBackOff()));
  }
});

The HTTPRequestInitializer will be called every time a HTTPRequest is constructed and sets the IOExceptionHandler. From there on the MediaUploadErrorHandler will first pass the Exception to the HttpBackOffIOExceptionHandler which may sleep for a while before allowing a retry. After that the MediaUploadErrorHandler will try to continue the upload.

Note that credential is an HttpRequestInitializer as well and you need both initializers to execute. Thus in my example, credential is called within the Initializer that I added.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top