Skip to main content

HTTP REQUESTS

File Uploads

Overview

Karate provides comprehensive support for file uploads and multipart requests, making it easy to test endpoints that accept files, images, documents, and other binary data.

Basic File Upload

Single File Upload

# Upload a PDF file
* multipart file myFile = { read: 'test.pdf', filename: 'upload-name.pdf', contentType: 'application/pdf' }
* multipart field message = 'File upload test'
* method post
* status 200

# Upload an image
* multipart file photo = { read: 'classpath:images/profile.jpg', filename: 'profile.jpg', contentType: 'image/jpeg' }
* method post
```gherkin

### File Upload Parameters

```gherkin
# Complete file configuration
* def fileConfig = {
read: 'classpath:documents/report.pdf', # File path
filename: 'monthly-report.pdf', # Name sent to server
contentType: 'application/pdf' # MIME type
}
* multipart file document = fileConfig
```gherkin

## Multiple File Uploads

### Sequential Files

```gherkin
# Upload multiple files individually
* multipart file file1 = { read: 'doc1.pdf', filename: 'document1.pdf', contentType: 'application/pdf' }
* multipart file file2 = { read: 'doc2.pdf', filename: 'document2.pdf', contentType: 'application/pdf' }
* multipart file file3 = { read: 'image.png', filename: 'photo.png', contentType: 'image/png' }
* method post
```gherkin

### Batch File Upload

```gherkin
# Upload multiple files using multipart files
* def files = {}
* set files.file1 = { read: 'test1.pdf', filename: 'upload1.pdf', contentType: 'application/pdf' }
* set files.file2 = { read: 'test2.pdf', filename: 'upload2.pdf', contentType: 'application/pdf' }
* multipart files files

# Dynamic file list
* def uploadFiles = function(filePaths) {
var result = {};
for (var i = 0; i < filePaths.length; i++) {
result['file' + i] = {
read: filePaths[i],
filename: 'upload' + i + '.pdf',
contentType: 'application/pdf'
};
}
return result;
}
* def filesToUpload = ['file1.pdf', 'file2.pdf', 'file3.pdf']
* multipart files uploadFiles(filesToUpload)
```gherkin

## Multipart Form Data

### Mixed Content Types

```gherkin
# Combine files with form fields
* multipart file avatar = { read: 'avatar.jpg', filename: 'avatar.jpg', contentType: 'image/jpeg' }
* multipart field name = 'John Doe'
* multipart field email = 'john@example.com'
* multipart field metadata = { tags: ['profile', 'avatar'], size: 'medium' }
* method post
```gherkin

### Complex Multipart Requests

```gherkin
# Multiple fields and files
* multipart field userId = '123'
* multipart field profile = read('user-profile.json')
* multipart file resume = { read: 'resume.pdf', filename: 'resume.pdf', contentType: 'application/pdf' }
* multipart file coverLetter = { read: 'cover.pdf', filename: 'cover.pdf', contentType: 'application/pdf' }
* multipart field preferences = { notifications: true, newsletter: false }
* method post
```gherkin

### JSON in Multipart

```gherkin
# Send JSON as multipart field
* def userData = {
name: 'Alice',
age: 30,
preferences: {
theme: 'dark',
language: 'en'
}
}
* multipart field data = userData
* multipart file document = { read: 'doc.pdf', filename: 'document.pdf' }
* method post
```gherkin

## Binary Data Handling

### Base64 Encoded Files

```gherkin
# Upload base64 encoded file
* def base64File = read('classpath:data/encoded-file.txt')
* def decoded = java.util.Base64.decoder.decode(base64File)
* multipart file upload = { value: decoded, filename: 'decoded.bin', contentType: 'application/octet-stream' }

# Encode file before sending
* def fileBytes = read('classpath:images/test.png')
* def encoded = java.util.Base64.encoder.encodeToString(fileBytes)
* request { image: encoded, type: 'base64' }
```gherkin

### Raw Binary Upload

```gherkin
# Direct binary upload
* def binaryData = read('classpath:data/binary-file.dat')
* header Content-Type = 'application/octet-stream'
* request binaryData
* method post

# Streaming large files
* def largeFile = karate.readAsStream('classpath:large-file.zip')
* header Content-Type = 'application/zip'
* request largeFile
```gherkin

## Dynamic File Uploads

### Conditional File Upload

```gherkin
# Upload file based on condition
* def shouldUploadPhoto = userType == 'premium'
* if (shouldUploadPhoto) multipart file photo = { read: 'photo.jpg', filename: 'photo.jpg' }
* multipart field userId = userId
* method post
```gherkin

### Generated Files

```gherkin
# Create and upload temporary file
* def createTempFile =
"""
function(content) {
var tempFile = java.io.File.createTempFile('test', '.txt');
var writer = new java.io.FileWriter(tempFile);
writer.write(content);
writer.close();
return tempFile.getAbsolutePath();
}
"""

* def tempPath = createTempFile('Test content for upload')
* multipart file tempFile = { read: '#(tempPath)', filename: 'test.txt', contentType: 'text/plain' }
* method post
```gherkin

### File Path Resolution

```gherkin
# Different path types
* multipart file file1 = { read: 'file.pdf' } # Relative to feature file
* multipart file file2 = { read: 'classpath:files/doc.pdf' } # Classpath
* multipart file file3 = { read: 'file:///absolute/path/file.pdf' } # Absolute path
* multipart file file4 = { read: '#(dynamicPath)' } # Variable path
```gherkin

## Advanced Upload Patterns

### Multipart/Related

```gherkin
# MIME multipart/related (for SOAP with attachments)
* configure charset = null
* header Content-Type = 'multipart/related; boundary=----=_Part_0_1468667539.1524054605020'
* def mainBody = read('soap-request.xml')
* def attachment = read('attachment.pdf')
* multipart entity mainBody
* multipart entity attachment
* method post
```gherkin

### Custom Content Headers

```gherkin
# Add custom headers to multipart parts
* def fileWithHeaders = {
read: 'document.pdf',
filename: 'important.pdf',
contentType: 'application/pdf',
headers: {
'Content-ID': '<document123>',
'Content-Description': 'Important Document'
}
}
* multipart file doc = fileWithHeaders
```gherkin

### Chunked Upload

```gherkin
# Simulate chunked upload
* def uploadChunk = function(chunkData, chunkNumber, totalChunks) {
karate.call('upload-chunk.feature', {
data: chunkData,
chunk: chunkNumber,
total: totalChunks,
sessionId: sessionId
});
}

# Split and upload file
* def fileData = read('large-file.dat')
* def chunkSize = 1024 * 1024 # 1MB chunks
* def chunks = splitIntoChunks(fileData, chunkSize)
* karate.forEach(chunks, function(chunk, i) {
uploadChunk(chunk, i + 1, chunks.length)
})
```gherkin

## File Upload Validation

### Response Validation

```gherkin
Scenario: Validate file upload response
* multipart file upload = { read: 'test.pdf', filename: 'test.pdf' }
* method post
* status 200
* match response contains {
fileId: '#string',
filename: 'test.pdf',
size: '#number',
contentType: 'application/pdf'
}
* def fileId = response.fileId
```gherkin

### Progress Tracking

```gherkin
# Mock progress tracking
* def trackUpload = function(file) {
var size = new java.io.File(file).length();
karate.log('Uploading file, size:', size, 'bytes');
return { file: file, size: size, startTime: new Date().getTime() };
}

* def uploadInfo = trackUpload('large-file.zip')
* multipart file upload = { read: '#(uploadInfo.file)', filename: 'large.zip' }
* method post
* def uploadTime = new Date().getTime() - uploadInfo.startTime
* print 'Upload completed in', uploadTime, 'ms'
```gherkin

## Error Handling

### File Size Validation

```gherkin
# Check file size before upload
* def checkFileSize = function(path, maxSize) {
var file = new java.io.File(path);
if (file.length() > maxSize) {
karate.fail('File too large: ' + file.length() + ' bytes');
}
return true;
}

* def filePath = 'large-file.pdf'
* def maxSize = 10 * 1024 * 1024 # 10MB
* eval checkFileSize(filePath, maxSize)
* multipart file upload = { read: '#(filePath)', filename: 'file.pdf' }
```gherkin

### Missing File Handling

```gherkin
# Handle missing files gracefully
* def uploadIfExists = function(path) {
try {
var file = new java.io.File(path);
if (file.exists()) {
return { read: path, filename: file.getName() };
}
} catch(e) {
karate.log('File not found:', path);
}
return null;
}

* def optionalFile = uploadIfExists('optional-file.pdf')
* if (optionalFile) multipart file upload = optionalFile
```gherkin

## Performance Optimization

### Parallel Uploads

```gherkin
# Upload files in parallel
* def uploadFile = function(filePath) {
return karate.call('single-upload.feature', { file: filePath });
}

* def files = ['file1.pdf', 'file2.pdf', 'file3.pdf']
* def results = karate.parallel(files, uploadFile)
* match each results == { status: 200, fileId: '#string' }
```gherkin

### Compression Before Upload

```gherkin
# Compress before uploading
* def compressFile = function(inputPath, outputPath) {
var input = new java.io.FileInputStream(inputPath);
var output = new java.util.zip.GZIPOutputStream(new java.io.FileOutputStream(outputPath));
var buffer = Java.type('byte[]')(1024);
var len;
while ((len = input.read(buffer)) > 0) {
output.write(buffer, 0, len);
}
input.close();
output.close();
return outputPath;
}

* def compressed = compressFile('large-file.json', 'compressed.gz')
* multipart file upload = { read: '#(compressed)', filename: 'data.gz', contentType: 'application/gzip' }
```gherkin

## Best Practices

### File Management

```gherkin
# ✅ Good: Clean up temporary files
* def cleanup = function(path) {
try {
new java.io.File(path).delete();
} catch(e) {}
}

* def tempFile = createTempFile('test data')
* multipart file upload = { read: '#(tempFile)', filename: 'temp.txt' }
* method post
* eval cleanup(tempFile)
```gherkin

### Error Prevention

```gherkin
# ✅ Good: Validate file type
* def validateFileType = function(path, allowedTypes) {
var filename = new java.io.File(path).getName();
var extension = filename.substring(filename.lastIndexOf('.') + 1);
if (!allowedTypes.includes(extension)) {
karate.fail('Invalid file type: ' + extension);
}
}

* eval validateFileType('document.pdf', ['pdf', 'doc', 'docx'])
```gherkin

### Documentation

```gherkin
# ✅ Good: Document file requirements
Scenario: Upload profile picture
"""
Requirements:
- File type: JPEG or PNG
- Max size: 5MB
- Dimensions: 200x200 to 2000x2000
"""
* def imageFile = 'profile.jpg'
* eval validateImageRequirements(imageFile)
* multipart file avatar = { read: '#(imageFile)', filename: 'avatar.jpg' }
* method post
```gherkin

## Next Steps

- Learn about [Response Handling](/docs/http-responses/status-codes) for upload validation
- Explore [Assertions](/docs/assertions/match-keyword) for response testing
- Understand [Reusability](/docs/reusability/calling-features) for common upload patterns