retrofit icon indicating copy to clipboard operation
retrofit copied to clipboard

java.net.SocketException: Broken pipe (Write failed) - Upload Multipart and PUT with 1GB file

Open vhsvuong86 opened this issue 3 years ago • 1 comments
trafficstars

The stacktrace error java.net.SocketException: Broken pipe (Write failed) at java.base/java.net.SocketOutputStream.socketWrite0(Native Method) at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110) at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150) at okio.OutputStreamSink.write(JvmOkio.kt:53) at okio.AsyncTimeout$sink$1.write(AsyncTimeout.kt:103) at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.kt:235) at okio.RealBufferedSink.write(RealBufferedSink.kt:145) at okhttp3.internal.http1.Http1ExchangeCodec$KnownLengthSink.write(Http1ExchangeCodec.kt:289) at okio.ForwardingSink.write(ForwardingSink.kt:29) at okhttp3.internal.connection.Exchange$RequestBodySink.write(Exchange.kt:218) at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.kt:235) at okio.RealBufferedSink.writeAll(RealBufferedSink.kt:184) at okhttp3.RequestBody$Companion$asRequestBody$1.writeTo(RequestBody.kt:167) at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.kt:157) at okhttp3.MultipartBody.writeTo(MultipartBody.kt:93) at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:59) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:152) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197) at okhttp3.internal.connection.RealCall.execute(RealCall.kt:148) at retrofit2.OkHttpCall.execute(OkHttpCall.java:190)

The interface:

@Multipart
    @PUT("/api/spaces/{serviceCode}/{spaceId}/files/{blockId}")
    Call<UploadOIDResponse> uploadOIDFile(@Path("serviceCode") String serviceCode,
                                       @Path("spaceId") String spaceId,
                                       @Path("blockId") String blockId,
                                       @Part MultipartBody.Part file,
                                       @HeaderMap Map<String, String> headers,
                                       @Query("sort") String sort
    );

The implementation:

RequestBody requestBody = RequestBody.create(
                MediaType.parse("application/octet-stream"), file);

 MultipartBody.Part filePart = MultipartBody.Part.createFormData("uploaded_file", file.getName(), requestBody);
Call<ObsMigrationApi.UploadOIDResponse> callSync = obsMigrationApi.uploadOIDFile(serviceCode, spaceId, fileName, filePart, headers, "true");
Response<ObsMigrationApi.UploadOIDResponse> response = callSync.execute();        

The retrofit client:

        final Builder builder = new OkHttpClient().newBuilder();

        final OkHttpClient client = builder
                .readTimeout(Duration.ZERO)
                .writeTimeout(Duration.ZERO)
                .connectTimeout(Duration.ZERO)
                .build();
        
        final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(client)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

In the beginning, I convert the file into the [] byte. It can upload the file successfully but it causes the OutOrMemory exception. So I decided to Multipart here. As I know the Multipart will stream the file to and write into the socket. Could you please help resolve this issue?

======= Retrofit: 2.8.1 The okHttpClient: 4.5.0 group: 'com.squareup.okhttp3', version: '4.5.0'

vhsvuong86 avatar May 31 '22 17:05 vhsvuong86

I have the same problem and the same stacktrace, any news?

JuanchiFraga avatar Jun 09 '22 16:06 JuanchiFraga

When the amount of data written exceeds the capacity of the receiving buffer, the connection may be closed and thrown java.net.SocketException: Broken pipe (Write failed)

tomridder avatar Apr 12 '23 10:04 tomridder