Q21 of 40 · Karate
How do you handle file uploads in Karate?
KarateMidkaratefile-uploadmultipartapi-testing
Short answer
Short answer: Use the multipart keyword: * multipart file = { read: 'classpath:files/test.csv', filename: 'data.csv', contentType: 'text/csv' } followed by * multipart field = { description: 'Monthly data' } for other form fields. Karate sets Content-Type: multipart/form-data automatically. Then When method POST triggers the upload.
Detail
Karate's multipart keyword configures individual parts of a multipart/form-data request:
# File part — read from classpath
* multipart file = { read: 'classpath:data/users.csv', filename: 'users.csv', contentType: 'text/csv' }
# Additional form fields
* multipart field = { description: 'User import', batchSize: '100' }
# Send the request
Given path '/imports'
When method POST
Then status 202
And match response.jobId == '#string'
Multipart properties:
read— file path on classpath (or absolute path); Karate reads the bytesfilename— the filename sent in the Content-Disposition headercontentType— MIME type of the file part; defaults to application/octet-stream if omittedvalue— use instead ofreadto send a string value as a file part
Do not set Content-Type manually — Karate sets it automatically with the boundary parameter.
Asserting the upload result: the POST response typically returns a job ID (async processing) or a count (sync). Use Awaitility / polling for async imports.
// EXAMPLE
file-upload.feature
Feature: CSV file upload
Background:
* url karate.properties['api.base.url']
* header Authorization = 'Bearer ' + bearerToken
Scenario: Upload user CSV returns a job ID
* multipart file = { read: 'classpath:data/100-users.csv', filename: 'users.csv', contentType: 'text/csv' }
* multipart field = { description: 'Bulk import test', notify: 'false' }
Given path '/imports/users'
When method POST
Then status 202
And match response.jobId == '#string'
And match response.status == 'QUEUED'
And match response.fileSize == '#number'
Scenario: Upload oversized file returns 413
* multipart file = { read: 'classpath:data/oversized.csv', filename: 'big.csv', contentType: 'text/csv' }
Given path '/imports/users'
When method POST
Then status 413
And match response.error contains 'file size'// WHAT INTERVIEWERS LOOK FOR
Correct multipart keyword syntax, the read vs value distinction, knowing not to set Content-Type manually, and testing error cases (oversized file, wrong content type) in addition to the happy path.
// COMMON PITFALL
Setting * header Content-Type = 'multipart/form-data' manually — this overwrites the auto-generated boundary, causing the server to fail parsing the request body with a 400 error.