or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compression-utilities.mdcontent-management.mdcookie-handling.mdhttp-headers.mdhttp-methods-status.mdhttp-parsing-generation.mdindex.mdmultipart-processing.mdpath-mapping.mduri-processing.md

multipart-processing.mddocs/

0

# Multi-Part Processing

1

2

Multi-part content handling for form data, file uploads, and byte ranges with async processing support, compliance validation, and streaming capabilities.

3

4

## Capabilities

5

6

### MultiPart Class

7

8

Namespace class for multi-part content processing with parsing, generation, and boundary utilities.

9

10

```java { .api }

11

/**

12

* Namespace class for multi-part content support

13

*/

14

class MultiPart {

15

/** Extract boundary parameter from Content-Type header */

16

static String extractBoundary(String contentType);

17

18

/** Generate multipart boundary with prefix and random characters */

19

static String generateBoundary(String prefix, int randomLength);

20

21

/**

22

* Individual part within multi-part content

23

*/

24

abstract static class Part implements Content.Source.Factory, Closeable {

25

/** Get part name from Content-Disposition header */

26

String getName();

27

28

/** Get filename from Content-Disposition header */

29

String getFileName();

30

31

/** Get part headers */

32

HttpFields getHeaders();

33

34

/** Get part content as source */

35

Content.Source getContentSource();

36

37

/** Get part content length */

38

long getLength();

39

40

/** Get part content type */

41

String getContentType();

42

43

/** Check if part represents a file upload */

44

boolean isFile();

45

46

/** Close part and release resources */

47

void close();

48

}

49

50

/**

51

* Multi-part content parser

52

*/

53

static class Parser {

54

/** Create parser with boundary and buffer pool */

55

Parser(String boundary, ByteBufferPool bufferPool);

56

57

/** Parse content source into parts */

58

void parse(Content.Source source, PartHandler handler);

59

60

/** Interface for handling parsed parts */

61

interface PartHandler {

62

/** Handle parsed part */

63

void handle(Part part);

64

}

65

}

66

}

67

```

68

69

### MultiPartFormData Class

70

71

Specialized multi-part processing for form data with async parsing.

72

73

```java { .api }

74

/**

75

* Multi-part form data processing with async support

76

*/

77

class MultiPartFormData {

78

/** Create form data processor with default configuration */

79

MultiPartFormData();

80

81

/** Create with custom configuration */

82

MultiPartFormData(MultiPartConfig config);

83

84

/** Parse multi-part content asynchronously */

85

CompletableFuture<Parts> parse(Content.Source source);

86

87

/** Parse multi-part content synchronously (blocking) */

88

Parts from(Content.Source source);

89

90

/** Parse with content type header */

91

CompletableFuture<Parts> parse(Content.Source source, String contentType);

92

93

/** Get maximum part size */

94

long getMaxPartSize();

95

96

/** Set maximum part size */

97

void setMaxPartSize(long maxPartSize);

98

99

/** Get maximum file size for uploads */

100

long getMaxFileSize();

101

102

/** Set maximum file size for uploads */

103

void setMaxFileSize(long maxFileSize);

104

105

/** Get maximum request size */

106

long getMaxRequestSize();

107

108

/** Set maximum request size */

109

void setMaxRequestSize(long maxRequestSize);

110

111

/**

112

* Collection of parsed multi-part form parts

113

*/

114

interface Parts extends Iterable<MultiPart.Part> {

115

/** Get part by name */

116

MultiPart.Part get(String name);

117

118

/** Get all parts with given name */

119

List<MultiPart.Part> getAll(String name);

120

121

/** Get part names */

122

Set<String> getNames();

123

124

/** Get all parts as list */

125

List<MultiPart.Part> asList();

126

127

/** Get number of parts */

128

int size();

129

130

/** Check if empty */

131

boolean isEmpty();

132

133

/** Release all parts */

134

void release();

135

}

136

}

137

```

138

139

### MultiPartByteRanges Class

140

141

Multi-part byte range processing for HTTP Range requests.

142

143

```java { .api }

144

/**

145

* Multi-part byte ranges for HTTP Range responses

146

*/

147

class MultiPartByteRanges {

148

/** Create byte ranges with content type */

149

MultiPartByteRanges(String contentType);

150

151

/** Add byte range part */

152

void addPart(ByteRange range, Content.Source content);

153

154

/** Get boundary string */

155

String getBoundary();

156

157

/** Get content type with boundary */

158

String getContentType();

159

160

/** Get parts as content source */

161

Content.Source getContentSource();

162

163

/** Get total content length */

164

long getContentLength();

165

}

166

```

167

168

### MultiPartConfig Class

169

170

Configuration for multi-part processing with size limits and temp directory settings.

171

172

```java { .api }

173

/**

174

* Configuration for multi-part processing

175

*/

176

class MultiPartConfig {

177

/** Create configuration with default settings */

178

MultiPartConfig();

179

180

/** Create with size limits */

181

MultiPartConfig(long maxFileSize, long maxRequestSize, int fileSizeThreshold);

182

183

/** Create with full configuration */

184

MultiPartConfig(long maxFileSize, long maxRequestSize,

185

int fileSizeThreshold, String location);

186

187

/** Get maximum file size for individual uploads */

188

long getMaxFileSize();

189

190

/** Get maximum total request size */

191

long getMaxRequestSize();

192

193

/** Get file size threshold for writing to disk */

194

int getFileSizeThreshold();

195

196

/** Get temporary file location */

197

String getLocation();

198

}

199

```

200

201

### MultiPartCompliance Class

202

203

Multi-part compliance modes and violation handling.

204

205

```java { .api }

206

/**

207

* Multi-part compliance modes and validation

208

*/

209

class MultiPartCompliance {

210

/** RFC 7578 compliant parsing */

211

static final MultiPartCompliance RFC7578;

212

213

/** Legacy compatibility mode */

214

static final MultiPartCompliance LEGACY;

215

216

/** Check if violation is allowed */

217

boolean allows(Violation violation);

218

219

/** Get allowed violations */

220

Set<Violation> getAllowed();

221

222

/** Get compliance mode name */

223

String getName();

224

225

/**

226

* Multi-part compliance violations

227

*/

228

enum Violation {

229

/** No boundary specified */

230

NO_BOUNDARY,

231

232

/** Invalid boundary characters */

233

INVALID_BOUNDARY,

234

235

/** Missing final boundary */

236

NO_FINAL_BOUNDARY,

237

238

/** Invalid Content-Disposition header */

239

INVALID_CONTENT_DISPOSITION,

240

241

/** Duplicate part names */

242

DUPLICATE_NAMES;

243

}

244

}

245

```

246

247

### ByteRange Class

248

249

HTTP Range request processing for partial content delivery.

250

251

```java { .api }

252

/**

253

* HTTP Range request processing

254

*/

255

class ByteRange {

256

/** Create byte range */

257

ByteRange(long first, long last);

258

259

/** Get first byte position */

260

long getFirst();

261

262

/** Get last byte position */

263

long getLast();

264

265

/** Get range length */

266

long getLength();

267

268

/** Check if range is suffix range */

269

boolean isSuffix();

270

271

/** Get range as Content-Range header value */

272

String toHeaderValue(long contentLength);

273

274

/** Parse Range header value */

275

static List<ByteRange> parse(String rangeHeader, long contentLength);

276

277

/** Parse single range specification */

278

static ByteRange parseRange(String range, long contentLength);

279

280

/** Check if ranges are satisfiable */

281

static boolean satisfiable(List<ByteRange> ranges, long contentLength);

282

}

283

```

284

285

**Usage Examples:**

286

287

```java

288

import org.eclipse.jetty.http.*;

289

import java.util.concurrent.CompletableFuture;

290

291

// Parse multi-part form data asynchronously

292

MultiPartConfig config = new MultiPartConfig(

293

10 * 1024 * 1024, // maxFileSize: 10MB

294

50 * 1024 * 1024, // maxRequestSize: 50MB

295

8192, // fileSizeThreshold: 8KB

296

"/tmp" // temp directory

297

);

298

299

MultiPartFormData formData = new MultiPartFormData(config);

300

301

// Async parsing

302

Content.Source requestBody = getRequestBodySource();

303

CompletableFuture<MultiPartFormData.Parts> future =

304

formData.parse(requestBody, "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");

305

306

future.thenAccept(parts -> {

307

// Process form fields

308

MultiPart.Part textField = parts.get("username");

309

if (textField != null) {

310

String username = readPartContent(textField);

311

}

312

313

// Process file uploads

314

MultiPart.Part fileUpload = parts.get("avatar");

315

if (fileUpload != null && fileUpload.isFile()) {

316

String filename = fileUpload.getFileName();

317

String contentType = fileUpload.getContentType();

318

long size = fileUpload.getLength();

319

320

// Save uploaded file

321

saveFile(fileUpload.getContentSource(), filename);

322

}

323

324

// Release resources

325

parts.release();

326

});

327

328

// Synchronous parsing

329

MultiPartFormData.Parts parts = formData.from(requestBody);

330

331

// Iterate through all parts

332

for (MultiPart.Part part : parts) {

333

String name = part.getName();

334

String filename = part.getFileName();

335

HttpFields headers = part.getHeaders();

336

337

if (part.isFile()) {

338

// Handle file upload

339

processFileUpload(part);

340

} else {

341

// Handle form field

342

String value = readPartContent(part);

343

}

344

}

345

346

// Get multiple parts with same name (e.g., checkboxes)

347

List<MultiPart.Part> selectedItems = parts.getAll("items");

348

for (MultiPart.Part item : selectedItems) {

349

String value = readPartContent(item);

350

}

351

352

// Create multi-part content programmatically

353

MultiPart multiPart = new MultiPart("----WebKitFormBoundary7MA4YWxkTrZu0gW");

354

355

// Add text part

356

MultiPart.Part textPart = createTextPart("username", "john.doe");

357

multiPart.addPart(textPart);

358

359

// Add file part

360

MultiPart.Part filePart = createFilePart("document", "report.pdf",

361

"application/pdf", fileContent);

362

multiPart.addPart(filePart);

363

364

// Multi-part byte ranges for HTTP Range responses

365

MultiPartByteRanges byteRanges = new MultiPartByteRanges("text/plain");

366

367

// Add range parts

368

ByteRange range1 = new ByteRange(0, 499); // bytes 0-499

369

ByteRange range2 = new ByteRange(1000, 1499); // bytes 1000-1499

370

371

byteRanges.addPart(range1, getContentSource(0, 500));

372

byteRanges.addPart(range2, getContentSource(1000, 500));

373

374

String contentType = byteRanges.getContentType();

375

// "multipart/byteranges; boundary=..."

376

377

// Parse HTTP Range header

378

String rangeHeader = "bytes=0-499,1000-1499";

379

long contentLength = 2000;

380

List<ByteRange> ranges = ByteRange.parse(rangeHeader, contentLength);

381

382

for (ByteRange range : ranges) {

383

long first = range.getFirst();

384

long last = range.getLast();

385

long length = range.getLength();

386

387

String contentRange = range.toHeaderValue(contentLength);

388

// "bytes 0-499/2000" or "bytes 1000-1499/2000"

389

}

390

391

// Check if ranges are satisfiable

392

boolean satisfiable = ByteRange.satisfiable(ranges, contentLength);

393

394

// Multi-part compliance handling

395

MultiPartCompliance compliance = MultiPartCompliance.RFC7578;

396

ComplianceViolation.Listener listener =

397

(mode, violation, details) -> {

398

System.err.println("Multi-part violation: " + violation + " - " + details);

399

};

400

401

// Helper methods (implementation dependent)

402

private String readPartContent(MultiPart.Part part) {

403

// Read part content as string

404

return null; // Implementation specific

405

}

406

407

private void saveFile(Content.Source source, String filename) {

408

// Save file to disk

409

}

410

411

private void processFileUpload(MultiPart.Part part) {

412

// Process uploaded file

413

}

414

415

private MultiPart.Part createTextPart(String name, String value) {

416

// Create text form field part

417

return null; // Implementation specific

418

}

419

420

private MultiPart.Part createFilePart(String name, String filename,

421

String contentType, byte[] content) {

422

// Create file upload part

423

return null; // Implementation specific

424

}

425

426

private Content.Source getRequestBodySource() {

427

// Get request body content source

428

return null; // Implementation specific

429

}

430

431

private Content.Source getContentSource(long offset, long length) {

432

// Get content source for byte range

433

return null; // Implementation specific

434

}

435

```