Problem when uploading video: Stream was reset: NO_ERROR

9.2k Views Asked by At

I'm working on an app that uploads videos to Vimeo using the TUS approach.

I wrote a simple wrapper for Fast Android Networking to use for uploading each part of the video file.

fun patch(
    destination: RequestDestination = RequestDestination.Api,
    url: String,
    headers: Map<String, Any> = mapOf(),
    body: ByteArray? = null,
    contentType: String? = null,
    priority: Priority = Priority.MEDIUM,
    jsonRequest: Boolean = true,
    success: (Any?) -> Unit,
    failure: (ANError?) -> Unit
) {
    val requestUrlString = getFullUrl(destination, url) // Determines the destination URL, is working correctly
    val request = AndroidNetworking.patch(requestUrlString)
    setRequestAttributes(request, headers, destination, priority) // Adds the request params, headers, etc to the request, works correctly
    if (contentType != null) { 
        request.setContentType(contentType) 
    }

    if (body != null) {
        request.addByteBody(body) 
    }

    request.build().getAsOkHttpResponse(object : OkHttpResponseListener {
        override fun onResponse(response: Response?) {
            success(response)
        }

        override fun onError(anError: ANError?) {
            failure(anError)
        }
    })
}

This seems to fail inconsistently, it sometimes works fine, and sometimes it doesn't. The parts uploaded are 70MB in size. The error thrown is:

com.androidnetworking.error.ANError: okhttp3.internal.http2.StreamResetException: stream was reset: NO_ERROR

Normally, I recover from errors by retrying the upload as TUS specifies, however, after getting the resources and retrying the patch, the network activity drops significantly (from a few Mbps to a few Kbps), and eventually a socket timeout occurs:

com.androidnetworking.error.ANError: java.net.SocketTimeoutException: timeout

Any ideas on what might be wrong here?

3

There are 3 best solutions below

2
On BEST ANSWER

I ended up using OkHttp3 directly to upload the data to Vimeo. Here's my solution:

fun basicPatch(
    url: String,
    headers: Map<String, String> = mapOf(),
    data: ByteArray,
    success: (Response) -> Unit,
    failure: (IOException) -> Unit
) {
    val tusMediaType = MediaType.parse("application/offset+octet-stream")
    val body = RequestBody.create(tusMediaType, data)

    val request = Request.Builder()
        .url(url)
        .headers(Headers.of(headers))
        .patch(body)
        .build()
    client.newCall(request).enqueue(object: Callback {
        override fun onFailure(call: Call, error: IOException) {
            failure(error)
        }

        override fun onResponse(call: Call, response: Response) {
            success(response)
            if (response.isSuccessful) {
                response.close()
            }
        }
    })
}
2
On

I had the same issue - getting RST_STREAM frame with an error code NO_ERROR. I was trying to upload a fairly big chunk of data through HTTP/2. Whenever I'd force to use HTTP/1_1 like so

List<Protocol> protocols = new ArrayList<Protocol>()
        {{
            add(Protocol.HTTP_1_1); // <-- The only protocol used
            //add(Protocol.HTTP_2); 
        }};
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(20L, TimeUnit.SECONDS)
                .writeTimeout  (20L, TimeUnit.SECONDS)
                .readTimeout   (20L, TimeUnit.SECONDS)
                .protocols(protocols)
                .build();

then I would get HTTP 413 Entity Too Large.

The solution was to explicitly tell proxy to set the client package limit to a higher value (1MB was the default). After that not only HTTP/1_1 worked, but HTTP/2 as well.

0
On

I found the solution:

MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);

Only set the type on the builder multipart body.