File Uploads & Multipart Data ## Business Purpose
Allow sending files and form data together in a single HTTP request using multipart/form-data encoding. ## Current Behaviors
- _encode_files static method in RequestEncodingMixin builds a multipart body from files and data src/requests/models.py:184.
- The method processes file entries that can be 2, 3, or 4-tuples: (filename, fileobj), (filename, fileobj, content_type), (filename, fileobj, content_type, custom_headers) src/requests/models.py:184.
- It raises ValueError if files is empty or if data is a string src/requests/models.py:184.
- File objects with non-string filename attributes are supported src/requests/test_requests.py:1868.
- Streaming upload with chunked transfer encoding is supported when body is a generator src/requests/models.py:422. ## Technical Implementation
The PreparedRequest.prepare_body method calls _encode_files if files are present, otherwise uses _encode_params for standard form data. The content type header includes the boundary. ## Definition of Done
- requests.post(url, files={'file': open('test.txt')}) uploads the file with correct Content-Type multipart/form-data.
- A file tuple with custom content type sets that Content-Type.
- Sending both data and files raises ValueError if data is a string.
- A file object with a byte stream is uploaded correctly.
- The boundary in the Content-Type header matches the body separator.