上传视频时出现问题:流已重置:NO_ERROR

Problem when uploading video: Stream was reset: NO_ERROR

我正在开发一款使用 TUS 方法将视频上传到 Vimeo 的应用。

我为快速 Android 网络编写了一个简单的包装器,用于上传视频文件的每个部分。

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)
        }
    })
}

这似乎经常失败,有时工作正常,有时却不行。 上传的部分大小为 70MB。 抛出的错误是:

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

通常,我会按照 TUS 指定的方式重试上传,从而从错误中恢复过来,但是,在获取资源并重试补丁后,网络 activity 明显下降(从几 Mbps 到几 Kbps),最终发生套接字超时:

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

关于这里可能有什么问题的任何想法?

我找到了解决方案:

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

仅在构建器多部分主体上设置类型。

我最终直接使用 OkHttp3 将数据上传到 Vimeo。 这是我的解决方案:

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()
            }
        }
    })
}

我遇到了同样的问题 - 得到 RST_STREAM 错误代码 NO_ERROR 的帧。我试图通过 HTTP/2 上传相当大的数据块。每当我强制使用 HTTP/1_1 时

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();

然后我会得到 HTTP 413 Entity Too Large

解决方案是明确告诉代理将客户端包限制设置为更高的值(默认值为 1MB)。在那之后,不仅 HTTP/1_1 有效,而且 HTTP/2 也有效。