or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-management.mdengine-system.mdform-data.mdhttp-utilities.mdindex.mdplugin-system.mdrequest-operations.mdresponse-handling.mdrouting-system.mdserver-framework.md

form-data.mddocs/

0

# Form Data Handling

1

2

URL-encoded and multipart form data support for form submissions and file uploads with type-safe DSL builders.

3

4

## Capabilities

5

6

### FormDataContent Class

7

8

URL-encoded form data content for application/x-www-form-urlencoded submissions.

9

10

```kotlin { .api }

11

/**

12

* Content for URL-encoded form data submissions

13

*/

14

class FormDataContent(

15

val formData: Parameters

16

) : OutgoingContent.ByteArrayContent() {

17

/** Content length in bytes */

18

override val contentLength: Long

19

20

/** Content type for URL-encoded form data */

21

override val contentType: ContentType = ContentType.Application.FormUrlEncoded

22

23

/**

24

* Get form data as byte array

25

* @return URL-encoded form data bytes

26

*/

27

override fun bytes(): ByteArray

28

}

29

```

30

31

**Usage Examples:**

32

33

```kotlin

34

import io.ktor.client.*

35

import io.ktor.client.request.*

36

import io.ktor.client.request.forms.*

37

import io.ktor.http.*

38

39

val client = HttpClient()

40

41

// Create form data content

42

val formData = Parameters.build {

43

append("username", "john.doe")

44

append("password", "secretpassword")

45

append("remember", "true")

46

}

47

48

val response = client.post("https://api.example.com/login") {

49

setBody(FormDataContent(formData))

50

}

51

```

52

53

### MultiPartFormDataContent Class

54

55

Multipart form data content for file uploads and complex form submissions.

56

57

```kotlin { .api }

58

/**

59

* Content for multipart form data submissions

60

*/

61

class MultiPartFormDataContent(

62

parts: List<PartData>,

63

val boundary: String = generateBoundary(),

64

override val contentType: ContentType = ContentType.MultiPart.FormData

65

.withParameter("boundary", boundary)

66

) : OutgoingContent.WriteChannelContent() {

67

/** Content length, null for streaming */

68

override var contentLength: Long? = null

69

70

/**

71

* Write multipart content to channel

72

* @param channel Output channel for writing data

73

*/

74

override suspend fun writeTo(channel: ByteWriteChannel)

75

}

76

```

77

78

### Form Submission Functions

79

80

Convenient functions for submitting forms without manually creating content objects.

81

82

```kotlin { .api }

83

/**

84

* Submit URL-encoded form data

85

* @param url Target URL

86

* @param formParameters Form parameters to submit

87

* @param encodeInQuery Whether to encode parameters in URL query string

88

* @param block Additional request configuration

89

* @return HttpResponse from server

90

*/

91

suspend fun HttpClient.submitForm(

92

url: String,

93

formParameters: Parameters = Parameters.Empty,

94

encodeInQuery: Boolean = false,

95

block: HttpRequestBuilder.() -> Unit = {}

96

): HttpResponse

97

98

/**

99

* Submit multipart form data with binary data

100

* @param url Target URL

101

* @param formData List of form parts including files

102

* @param block Additional request configuration

103

* @return HttpResponse from server

104

*/

105

suspend fun HttpClient.submitFormWithBinaryData(

106

url: String,

107

formData: List<PartData>,

108

block: HttpRequestBuilder.() -> Unit = {}

109

): HttpResponse

110

```

111

112

**Usage Examples:**

113

114

```kotlin

115

import io.ktor.client.*

116

import io.ktor.client.request.forms.*

117

import io.ktor.http.*

118

119

val client = HttpClient()

120

121

// Submit simple form

122

val response = client.submitForm(

123

url = "https://api.example.com/contact",

124

formParameters = Parameters.build {

125

append("name", "John Doe")

126

append("email", "john@example.com")

127

append("message", "Hello from Ktor!")

128

}

129

)

130

131

// Submit form with file upload

132

val formData = formData {

133

append("name", "John Doe")

134

append("file", fileBytes, Headers.build {

135

append(HttpHeaders.ContentDisposition, "filename=\"document.pdf\"")

136

append(HttpHeaders.ContentType, "application/pdf")

137

})

138

}

139

140

val uploadResponse = client.submitFormWithBinaryData(

141

url = "https://api.example.com/upload",

142

formData = formData

143

)

144

```

145

146

### Form Building DSL

147

148

Type-safe DSL for building multipart form data with support for text fields, files, and binary data.

149

150

```kotlin { .api }

151

/**

152

* Build form data using DSL

153

* @param block Form building block

154

* @return List of form parts

155

*/

156

fun formData(block: FormBuilder.() -> Unit): List<PartData>

157

158

/**

159

* Builder for constructing multipart form data

160

*/

161

class FormBuilder {

162

/**

163

* Append text field to form

164

* @param key Field name

165

* @param value Field value

166

*/

167

fun append(key: String, value: String)

168

169

/**

170

* Append text field with custom headers

171

* @param key Field name

172

* @param value Field value

173

* @param headers Custom headers for the part

174

*/

175

fun append(key: String, value: String, headers: Headers)

176

177

/**

178

* Append binary data to form

179

* @param key Field name

180

* @param value Binary data as byte array

181

* @param headers Custom headers for the part

182

*/

183

fun append(key: String, value: ByteArray, headers: Headers = Headers.Empty)

184

185

/**

186

* Append data from Input provider

187

* @param key Field name

188

* @param provider Function that provides Input stream

189

* @param headers Custom headers for the part

190

*/

191

fun append(

192

key: String,

193

provider: () -> Input,

194

headers: Headers = Headers.Empty

195

)

196

197

/**

198

* Append data from ByteReadChannel provider

199

* @param key Field name

200

* @param provider Function that provides ByteReadChannel

201

* @param headers Custom headers for the part

202

*/

203

fun append(

204

key: String,

205

provider: () -> ByteReadChannel,

206

headers: Headers = Headers.Empty

207

)

208

}

209

```

210

211

**Usage Examples:**

212

213

```kotlin

214

import io.ktor.client.*

215

import io.ktor.client.request.forms.*

216

import io.ktor.http.*

217

import io.ktor.utils.io.*

218

import java.io.File

219

220

val client = HttpClient()

221

222

// Build complex form with various field types

223

val formData = formData {

224

// Text fields

225

append("username", "john.doe")

226

append("description", "User profile update")

227

228

// File upload from byte array

229

append("avatar", avatarBytes, Headers.build {

230

append(HttpHeaders.ContentDisposition, "filename=\"avatar.jpg\"")

231

append(HttpHeaders.ContentType, "image/jpeg")

232

})

233

234

// File upload from File (JVM)

235

append("document", File("document.pdf").readBytes(), Headers.build {

236

append(HttpHeaders.ContentDisposition, "filename=\"document.pdf\"")

237

append(HttpHeaders.ContentType, "application/pdf")

238

})

239

240

// Streaming data

241

append("data", { ByteReadChannel(largeDataBytes) }, Headers.build {

242

append(HttpHeaders.ContentDisposition, "filename=\"data.bin\"")

243

append(HttpHeaders.ContentType, "application/octet-stream")

244

})

245

}

246

247

val response = client.submitFormWithBinaryData(

248

url = "https://api.example.com/profile/update",

249

formData = formData

250

) {

251

header("Authorization", "Bearer $token")

252

}

253

```

254

255

### PartData Types

256

257

Data classes representing different types of form parts.

258

259

```kotlin { .api }

260

/**

261

* Base class for form parts

262

*/

263

sealed class PartData {

264

/** Headers for this part */

265

abstract val headers: Headers

266

267

/** Release resources associated with this part */

268

abstract fun dispose()

269

}

270

271

/**

272

* Form part containing text data

273

*/

274

class PartData.FormItem(

275

val value: String,

276

override val headers: Headers

277

) : PartData()

278

279

/**

280

* Form part containing binary data

281

*/

282

class PartData.BinaryItem(

283

val provider: () -> Input,

284

override val headers: Headers

285

) : PartData()

286

287

/**

288

* Form part containing binary channel data

289

*/

290

class PartData.BinaryChannelItem(

291

val provider: () -> ByteReadChannel,

292

override val headers: Headers

293

) : PartData()

294

295

/**

296

* Form part containing file data

297

*/

298

class PartData.FileItem(

299

val provider: () -> Input,

300

override val headers: Headers

301

) : PartData()

302

```

303

304

### Content-Disposition Headers

305

306

Utilities for working with Content-Disposition headers in form data.

307

308

```kotlin { .api }

309

/**

310

* Content-Disposition header utilities

311

*/

312

object ContentDisposition {

313

/**

314

* Create Content-Disposition header for form field

315

* @param name Field name

316

* @return Content-Disposition header value

317

*/

318

fun formData(name: String): String = "form-data; name=\"$name\""

319

320

/**

321

* Create Content-Disposition header for file field

322

* @param name Field name

323

* @param filename File name

324

* @return Content-Disposition header value

325

*/

326

fun formData(name: String, filename: String): String =

327

"form-data; name=\"$name\"; filename=\"$filename\""

328

329

/**

330

* Create Content-Disposition header for attachment

331

* @param filename File name

332

* @return Content-Disposition header value

333

*/

334

fun attachment(filename: String): String = "attachment; filename=\"$filename\""

335

}

336

```

337

338

**Usage Examples:**

339

340

```kotlin

341

import io.ktor.client.request.forms.*

342

import io.ktor.http.*

343

344

val formData = formData {

345

// Simple field

346

append("message", "Hello World", Headers.build {

347

append(HttpHeaders.ContentDisposition, ContentDisposition.formData("message"))

348

})

349

350

// File field

351

append("upload", fileBytes, Headers.build {

352

append(HttpHeaders.ContentDisposition,

353

ContentDisposition.formData("upload", "document.pdf"))

354

append(HttpHeaders.ContentType, "application/pdf")

355

})

356

}

357

```

358

359

### Parameters Building

360

361

Utilities for building URL-encoded form parameters.

362

363

```kotlin { .api }

364

/**

365

* Parameters interface for form data

366

*/

367

interface Parameters : StringValues {

368

companion object {

369

/** Empty parameters instance */

370

val Empty: Parameters

371

372

/**

373

* Build parameters using DSL

374

* @param block Building block

375

* @return Built parameters

376

*/

377

fun build(block: ParametersBuilder.() -> Unit): Parameters

378

}

379

}

380

381

/**

382

* Builder for constructing parameters

383

*/

384

interface ParametersBuilder : StringValuesBuilder {

385

/**

386

* Append parameter value

387

* @param name Parameter name

388

* @param value Parameter value

389

*/

390

fun append(name: String, value: String)

391

392

/**

393

* Append multiple values for parameter

394

* @param name Parameter name

395

* @param values Parameter values

396

*/

397

fun appendAll(name: String, values: Iterable<String>)

398

399

/**

400

* Set parameter value (replaces existing)

401

* @param name Parameter name

402

* @param value Parameter value

403

*/

404

fun set(name: String, value: String)

405

406

/**

407

* Remove parameter

408

* @param name Parameter name to remove

409

*/

410

fun remove(name: String)

411

412

/**

413

* Clear all parameters

414

*/

415

fun clear()

416

417

/**

418

* Build final parameters

419

* @return Immutable parameters instance

420

*/

421

fun build(): Parameters

422

}

423

```

424

425

**Usage Examples:**

426

427

```kotlin

428

import io.ktor.client.request.forms.*

429

import io.ktor.http.*

430

431

// Build parameters for form submission

432

val parameters = Parameters.build {

433

append("search", "kotlin")

434

append("category", "programming")

435

append("tags", "multiplatform")

436

append("tags", "coroutines") // Multiple values for same key

437

set("limit", "50") // Replace any existing value

438

}

439

440

val response = client.submitForm(

441

url = "https://api.example.com/search",

442

formParameters = parameters

443

)

444

```

445

446

## Platform-Specific Support

447

448

### JVM File Support

449

450

Additional support for File objects on JVM platform.

451

452

```kotlin { .api }

453

/**

454

* JVM-specific file content support

455

*/

456

class LocalFileContent(

457

private val file: File

458

) : OutgoingContent.ReadChannelContent() {

459

override val contentLength: Long = file.length()

460

override fun readFrom(): ByteReadChannel

461

}

462

463

/**

464

* Set request body from File (JVM only)

465

* @param file File to upload

466

*/

467

fun HttpRequestBuilder.setBody(file: File)

468

469

/**

470

* Append file to form data (JVM only)

471

* @param key Field name

472

* @param file File to append

473

* @param headers Custom headers

474

*/

475

fun FormBuilder.appendFile(

476

key: String,

477

file: File,

478

headers: Headers = Headers.Empty

479

)

480

```

481

482

**Usage Examples (JVM only):**

483

484

```kotlin

485

import io.ktor.client.*

486

import io.ktor.client.request.*

487

import io.ktor.client.request.forms.*

488

import java.io.File

489

490

val client = HttpClient()

491

492

// Upload file directly

493

val file = File("document.pdf")

494

val response = client.post("https://api.example.com/upload") {

495

setBody(file)

496

}

497

498

// Include file in form

499

val formWithFile = formData {

500

append("title", "Important Document")

501

appendFile("document", file, Headers.build {

502

append(HttpHeaders.ContentType, "application/pdf")

503

})

504

}

505

```

506

507

## Types

508

509

Form data related types:

510

511

```kotlin { .api }

512

/**

513

* String values interface for parameters

514

*/

515

interface StringValues {

516

val caseInsensitiveName: Boolean

517

518

fun get(name: String): String?

519

fun getAll(name: String): List<String>?

520

fun names(): Set<String>

521

fun isEmpty(): Boolean

522

fun entries(): Set<Map.Entry<String, List<String>>>

523

524

operator fun contains(name: String): Boolean

525

fun forEach(body: (String, List<String>) -> Unit)

526

}

527

528

/**

529

* Headers interface extending StringValues

530

*/

531

interface Headers : StringValues {

532

companion object {

533

val Empty: Headers

534

535

fun build(block: HeadersBuilder.() -> Unit): Headers

536

}

537

}

538

539

/**

540

* Headers builder interface

541

*/

542

interface HeadersBuilder : StringValuesBuilder {

543

fun append(name: String, value: String)

544

fun appendAll(name: String, values: Iterable<String>)

545

fun set(name: String, value: String)

546

fun remove(name: String)

547

fun clear()

548

fun build(): Headers

549

}

550

551

/**

552

* Generate boundary for multipart content

553

* @return Random boundary string

554

*/

555

fun generateBoundary(): String

556

557

/**

558

* Input stream interface for reading data

559

*/

560

interface Input : Closeable {

561

fun readByte(): Byte

562

fun readBytes(count: Int): ByteArray

563

fun readAvailable(dst: ByteArray, offset: Int, length: Int): Int

564

}

565

```