1
+ package com.baeldung.fileupload
2
+
3
+ import com.github.kittinunf.fuel.core.FileDataPart
4
+ import com.github.kittinunf.fuel.httpUpload
5
+ import com.github.tomakehurst.wiremock.client.WireMock.aResponse
6
+ import com.github.tomakehurst.wiremock.client.WireMock.containing
7
+ import com.github.tomakehurst.wiremock.client.WireMock.matching
8
+ import com.github.tomakehurst.wiremock.client.WireMock.post
9
+ import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor
10
+ import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo
11
+ import com.github.tomakehurst.wiremock.junit.WireMockRule
12
+ import io.ktor.client.HttpClient
13
+ import io.ktor.client.engine.cio.CIO
14
+ import io.ktor.client.request.forms.formData
15
+ import io.ktor.client.request.forms.submitFormWithBinaryData
16
+ import io.ktor.client.statement.HttpStatement
17
+ import io.ktor.client.statement.readText
18
+ import io.ktor.http.Headers
19
+ import io.ktor.http.HttpHeaders
20
+ import kotlinx.coroutines.runBlocking
21
+ import okhttp3.Call
22
+ import okhttp3.Callback
23
+ import okhttp3.MediaType.Companion.toMediaTypeOrNull
24
+ import okhttp3.MultipartBody
25
+ import okhttp3.OkHttpClient
26
+ import okhttp3.Request
27
+ import okhttp3.RequestBody.Companion.asRequestBody
28
+ import okhttp3.Response
29
+ import okhttp3.ResponseBody
30
+ import okhttp3.internal.wait
31
+ import org.junit.jupiter.api.AfterEach
32
+ import org.junit.jupiter.api.BeforeEach
33
+ import org.junit.Rule
34
+ import org.junit.jupiter.api.Test
35
+ import retrofit2.Retrofit
36
+ import retrofit2.converter.gson.GsonConverterFactory
37
+ import retrofit2.http.Multipart
38
+ import retrofit2.http.POST
39
+ import retrofit2.http.Part
40
+ import java.io.File
41
+ import java.io.IOException
42
+
43
+ fun uploadFileFuel (filePath : String , uploadUrl : String ) {
44
+ val file = File (filePath)
45
+ uploadUrl.httpUpload()
46
+ .add(FileDataPart (file, name = " file" ))
47
+ .response { request, response, result ->
48
+ println (response)
49
+ }.get()
50
+ }
51
+
52
+ suspend fun uploadFileKtor (filePath : String , uploadUrl : String ) {
53
+ val client = HttpClient (CIO ) {}
54
+
55
+ val statement: HttpStatement = client.submitFormWithBinaryData(
56
+ url = uploadUrl,
57
+ formData = formData {
58
+ append(" file" , File (filePath).readBytes(), Headers .build {
59
+ append(HttpHeaders .ContentType , " application/octet-stream" )
60
+ append(HttpHeaders .ContentDisposition , " filename=${File (filePath).name} " )
61
+ })
62
+ }
63
+ )
64
+
65
+ println (statement.execute().readText())
66
+ client.close()
67
+ }
68
+
69
+ fun uploadFileOkHttp (filePath : String , uploadUrl : String ) {
70
+ val client = OkHttpClient ()
71
+ val file = File (filePath)
72
+ val requestBody = MultipartBody .Builder ()
73
+ .setType(MultipartBody .FORM )
74
+ .addFormDataPart(" file" , file.name, file.asRequestBody(" application/octet-stream" .toMediaTypeOrNull()))
75
+ .build()
76
+
77
+ val request = Request .Builder ()
78
+ .url(uploadUrl)
79
+ .post(requestBody)
80
+ .build()
81
+
82
+ println (client.newCall(request).execute())
83
+ }
84
+
85
+
86
+ interface UploadService {
87
+ @Multipart
88
+ @POST(" upload" )
89
+ fun uploadFile (@Part file : MultipartBody .Part ): retrofit2.Call <ResponseBody >
90
+ }
91
+
92
+ fun createUploadService (url : String ): UploadService {
93
+ val retrofit = Retrofit .Builder ()
94
+ .baseUrl(url)
95
+ .client(OkHttpClient ())
96
+ .addConverterFactory(GsonConverterFactory .create())
97
+ .build()
98
+
99
+ return retrofit.create(UploadService ::class .java)
100
+ }
101
+
102
+ fun uploadFileRetrofit (filePath : String , uploadUrl : String ) {
103
+ val file = File (filePath)
104
+ val requestBody = file.asRequestBody(" application/octet-stream" .toMediaTypeOrNull())
105
+ val multipartBody = MultipartBody .Part .createFormData(" file" , file.name, requestBody)
106
+
107
+ val service = createUploadService(uploadUrl)
108
+ val call = service.uploadFile(multipartBody)
109
+ println (call.execute().body()?.string())
110
+ }
111
+
112
+ class FileUploadUnitTest {
113
+ @Rule
114
+ @JvmField
115
+ val wireMockRule = WireMockRule (8080 )
116
+
117
+ @BeforeEach
118
+ fun startWireMock () {
119
+ if (wireMockRule.isRunning) return
120
+ wireMockRule.start()
121
+ }
122
+ @AfterEach
123
+ fun stopWireMock () {
124
+ wireMockRule.stop()
125
+ }
126
+
127
+ @Test
128
+ fun `Should upload file using Fuel` () {
129
+ wireMockRule.stubFor(post(urlEqualTo(" /upload" )).willReturn(aResponse().withStatus(200 )))
130
+
131
+ uploadFileFuel(" src/test/resources/testfile.txt" , " ${wireMockRule.baseUrl()} /upload" )
132
+
133
+ wireMockRule.verify(
134
+ postRequestedFor(urlEqualTo(" /upload" )).withHeader(" Content-Type" , containing(" multipart/form-data" ))
135
+ .withRequestBody(matching(" .*testfile.txt.*" ))
136
+ )
137
+
138
+ }
139
+
140
+ @Test
141
+ fun `Should upload file using Ktor` () = runBlocking {
142
+ wireMockRule.stubFor(post(urlEqualTo(" /upload" )).willReturn(aResponse().withStatus(200 )))
143
+
144
+ uploadFileKtor(" src/test/resources/testfile.txt" , " ${wireMockRule.baseUrl()} /upload" )
145
+
146
+ wireMockRule.verify(postRequestedFor(urlEqualTo(" /upload" )).withRequestBody(matching(" .*testfile.txt.*" )).withHeader(" Content-Type" , containing(" multipart/form-data" )))
147
+ }
148
+
149
+ @Test
150
+ fun `Should upload file using OkHttp` () {
151
+ wireMockRule.stubFor(post(urlEqualTo(" /upload" )).willReturn(aResponse().withStatus(200 )))
152
+
153
+ uploadFileOkHttp(" src/test/resources/testfile.txt" , " ${wireMockRule.baseUrl()} /upload" )
154
+
155
+ wireMockRule.verify(postRequestedFor(urlEqualTo(" /upload" )).withHeader(" Content-Type" , containing(" multipart/form-data" )).withRequestBody(matching(" .*testfile.txt.*" )))
156
+ }
157
+
158
+ @Test
159
+ fun `Should upload file using Retrofit` () {
160
+ wireMockRule.stubFor(post(urlEqualTo(" /upload" )).willReturn(aResponse().withStatus(200 )))
161
+
162
+ uploadFileRetrofit(" src/test/resources/testfile.txt" , wireMockRule.baseUrl())
163
+
164
+ wireMockRule.verify(postRequestedFor(urlEqualTo(" /upload" )).withHeader(" Content-Type" , containing(" multipart/form-data" )).withRequestBody(matching(" .*testfile.txt.*" )))
165
+ }
166
+ }
0 commit comments