Skip to content

Commit b73a4a0

Browse files
authored
[KTLN-866] Add Samples (#999)
* [KTLN-866] Add Samples * Merge with upstream * [KTLN-866] Add Samples
1 parent f3a34e4 commit b73a4a0

File tree

4 files changed

+232
-1
lines changed

4 files changed

+232
-1
lines changed

core-kotlin-modules/core-kotlin-io/pom.xml

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,73 @@
1313
<version>1.0.0-SNAPSHOT</version>
1414
</parent>
1515

16+
<properties>
17+
<okhttp.version>4.9.1</okhttp.version>
18+
<wiremock.version>2.31.0</wiremock.version>
19+
<fuel.version>2.3.1</fuel.version>
20+
<retrofit.version>2.9.0</retrofit.version>
21+
<ktor.version>1.5.4</ktor.version>
22+
<kotlinx.serialization.version>1.2.2</kotlinx.serialization.version>
23+
<junit.version>4.13.2</junit.version>
24+
</properties>
25+
1626
<dependencies>
27+
<!-- OkHttp -->
28+
<dependency>
29+
<groupId>com.squareup.okhttp3</groupId>
30+
<artifactId>okhttp</artifactId>
31+
<version>${okhttp.version}</version>
32+
</dependency>
33+
34+
<!-- WireMock -->
35+
<dependency>
36+
<groupId>com.github.tomakehurst</groupId>
37+
<artifactId>wiremock-jre8</artifactId>
38+
<version>${wiremock.version}</version>
39+
<scope>test</scope>
40+
</dependency>
41+
42+
<!-- Fuel -->
43+
<dependency>
44+
<groupId>com.github.kittinunf.fuel</groupId>
45+
<artifactId>fuel</artifactId>
46+
<version>${fuel.version}</version>
47+
</dependency>
48+
49+
<!-- Retrofit -->
50+
<dependency>
51+
<groupId>com.squareup.retrofit2</groupId>
52+
<artifactId>retrofit</artifactId>
53+
<version>${retrofit.version}</version>
54+
</dependency>
55+
<dependency>
56+
<groupId>com.squareup.retrofit2</groupId>
57+
<artifactId>converter-gson</artifactId>
58+
<version>${retrofit.version}</version>
59+
</dependency>
60+
61+
<!-- Ktor -->
62+
<dependency>
63+
<groupId>io.ktor</groupId>
64+
<artifactId>ktor-client-core-jvm</artifactId>
65+
<version>${ktor.version}</version>
66+
</dependency>
67+
<dependency>
68+
<groupId>io.ktor</groupId>
69+
<artifactId>ktor-client-cio-jvm</artifactId>
70+
<version>${ktor.version}</version>
71+
</dependency>
72+
73+
<!-- Kotlinx Serialization JSON for Ktor -->
74+
<dependency>
75+
<groupId>org.jetbrains.kotlinx</groupId>
76+
<artifactId>kotlinx-serialization-json</artifactId>
77+
<version>${kotlinx.serialization.version}</version>
78+
</dependency>
1779
<dependency>
1880
<groupId>commons-io</groupId>
1981
<artifactId>commons-io</artifactId>
2082
<version>2.15.1</version>
2183
</dependency>
2284
</dependencies>
23-
2485
</project>
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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+
}

core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/streamtofile/InputStreamToFileUnitTest.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@file:OptIn(ExperimentalPathApi::class)
2+
13
package com.baeldung.streamtofile
24

35
import org.assertj.core.api.Assertions.assertThat
@@ -6,6 +8,7 @@ import java.io.ByteArrayInputStream
68
import java.io.File
79
import java.nio.file.Files
810
import java.nio.file.Paths
11+
import kotlin.io.path.ExperimentalPathApi
912

1013
class InputStreamToFileUnitTest {
1114

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World!

0 commit comments

Comments
 (0)