使用OkHttp上传到预先签署的S3 URL失败

当我尝试使用OkHttp 3.9.1将文件上传到Amazon S3的预签名URL时,出现SSLexception: SSLException: Write error: ssl=0xa0b73280: I/O error during system call, Connection reset by peer

这是同样的问题,在另一个SO问题,但在我的情况下,它总是失败。 我只上传大小超过1MiB的文件,我还没有尝试过小文件。

正如我在这个问题的答案中提到的,切换到Java的HttpURLConnection解决了这个问题,上传完美。

这里是我的RequestBody实现(在Kotlin)从Android的Uri上传文件,我使用OkHttp的.put()方法:

 class UriRequestBody(private val file: Uri, private val contentResolver: ContentResolver, private val mediaType: MediaType = MediaType.parse("application/octet-stream")!!): RequestBody() { override fun contentLength(): Long = -1L override fun contentType(): MediaType? = mediaType override fun writeTo(sink: BufferedSink) { Okio.source((contentResolver.openInputStream(file))).use { sink.writeAll(it) } } } 

这里是我的HttpURLConnection实现:

 private fun uploadFileRaw(file: Uri, uploadUrl: String, contentResolver: ContentResolver) : Int { val url = URL(uploadUrl) val connection = url.openConnection() as HttpURLConnection connection.doOutput = true connection.requestMethod = "PUT" val out = connection.outputStream contentResolver.openInputStream(file).use { it.copyTo(out) } out.close() return connection.responseCode } 

OkHttp的做法有什么不同,可能会导致此SSLexception?

编辑:

这是OkHttp代码上传文件(使用默认的application/octet-stream MIMEtypes):

 val s3UploadClient = OkHttpClient().newBuilder() .connectTimeout(30_000L, TimeUnit.MILLISECONDS) .readTimeout(30_000L, TimeUnit.MILLISECONDS) .writeTimeout(60_000L, TimeUnit.MILLISECONDS) .retryOnConnectionFailure(true) .build() val body: RequestBody = UriRequestBody(file, contentResolver) val request = Request.Builder() .url(uploadUrl) .put(body) .build() s3UploadClient.newCall(request).execute() 

这是生成预先签名的上传URL的JavaScript服务器代码:

 const s3 = new aws.S3({ region: 'us-west-2', signatureVersion: 'v4' }); const signedUrlExpireSeconds = 60 * 5; const signedUrl = s3.getSignedUrl('putObject', { Bucket: config.bucket.name, Key: `${fileName}`, Expires: signedUrlExpireSeconds }); 

Interesting Posts