Skip to content

Commit

Permalink
Add example for uploading files
Browse files Browse the repository at this point in the history
  • Loading branch information
perklet committed Jan 19, 2024
1 parent 20e1d8b commit e982ae1
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 1 deletion.
3 changes: 2 additions & 1 deletion curl_cffi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"CurlInfo",
"CurlOpt",
"CurlMOpt",
"CurlMime",
"CurlECode",
"CurlHttpVersion",
"CurlError",
Expand All @@ -16,7 +17,7 @@
from ._wrapper import ffi, lib # type: ignore

from .const import CurlInfo, CurlMOpt, CurlOpt, CurlECode, CurlHttpVersion
from .curl import Curl, CurlError
from .curl import Curl, CurlError, CurlMime
from .aio import AsyncCurl

from .__version__ import __title__, __version__, __description__, __curl_version__
11 changes: 11 additions & 0 deletions curl_cffi/curl.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ def __init__(self, curl: Optional[Curl] = None):
def addpart(
self,
name: str,
*,
type: Optional[str] = None,
filename: Optional[str] = None,
filepath: Optional[Union[str, bytes, Path]] = None,
Expand Down Expand Up @@ -418,9 +419,19 @@ def addpart(
if fileobj is not None:
ret = lib.curl_mime_data(part, fileobj.read())

@classmethod
def from_list(cls, files: List[dict]):
form = cls()
for file in files:
form.addpart(**file)
return form

def attach(self, curl: Optional[Curl] = None):
c = curl if curl else self._curl
c.setopt(CurlOpt.MIMEPOST, self._form)

def close(self):
lib.curl_mime_free(self._form)

def __del__(self):
self.close()
4 changes: 4 additions & 0 deletions curl_cffi/requests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from io import BytesIO
from typing import Callable, Dict, Optional, Tuple, Union


from ..curl import CurlMime
from ..const import CurlHttpVersion, CurlWsFlag
from .cookies import Cookies, CookieTypes
from .models import Request, Response
Expand Down Expand Up @@ -63,6 +65,7 @@ def request(
http_version: Optional[CurlHttpVersion] = None,
debug: bool = False,
interface: Optional[str] = None,
multipart: Optional[CurlMime] = None,
) -> Response:
"""Send an http request.
Expand Down Expand Up @@ -122,6 +125,7 @@ def request(
default_headers=default_headers,
http_version=http_version,
interface=interface,
multipart=multipart,
)


Expand Down
44 changes: 44 additions & 0 deletions examples/upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
We do not support requests.post(url, files=...), for 2 reasons.
- Curl's mime struct need to be freed manually after each request.
- requests' files parameter is quite a mess, it's just not worth it.
You use the multipart instead, it's very simple and straightforward.
"""
from curl_cffi import requests, CurlMime


form = CurlMime()
form.addpart(
"image", # form field name
type="image/png", # mime type
filename="image.png", # filename seen by remote server
filepath="./image.png", # local file to upload
)

# you can add multiple files under the same field name
form.addpart(
"image",
type="image/jpg",
filename="image.jpg",
fileobj=open("./image.jpg"), # local file to upload, not the difference vs above
)

# from a list
form = CurlMime.from_list(
[
{
"name": "image",
"type": "image/png",
"filename": "image.png",
"filepath": "./image.png",
},
]
)

r = requests.get(url, multipart=form)

# close the form object, otherwise you have to wait for GC to recycle it. If you files
# are too large, you may run out of memory quickly.
form.close()

0 comments on commit e982ae1

Please sign in to comment.