跳到主要内容

RequestBody 与 UploadFile

RequestBody​

通过 body= 发送文件,避免先把整个文件读入 Mojo 内存;也可以发送有限的字节块列表。 不能与 content、data、json、files 同时使用。

RequestBody.from_file(path: String) raises HTTPError -> RequestBody
RequestBody.from_bytes(content: Bytes) raises HTTPError -> RequestBody
RequestBody.from_chunks(
chunks: List[Bytes],
*,
known_length: Bool = False,
replayable: Bool = False,
) raises HTTPError -> RequestBody

def content_length(self) raises HTTPError -> Optional[Int]
def close(mut self)
def is_closed(self) -> Bool

from_file 在构造时打开文件,发送时逐块读取。文件体可重放;修改文件可能导致 WriteError。 from_bytes 复制字节,生成可重放请求体。 from_chunks 在构造时复制列表中的字节,是有限内存数据源,不是回调或无限生成流。 默认长度未知且只能发送一次;known_length=True 声明字节长度, replayable=True 允许再次发送。

var response = req.post(
"https://httpbin.org/post",
body=req.RequestBody.from_file("report.csv"),
)
response.raise_for_status()

content_length() 对未知长度请求体返回 None。 RequestBody 的副本共享原生数据源状态:一次性请求体的别名不能重复发送。 关闭一个包装值会释放该值的引用,已准备的请求仍可保留数据源。

UploadFile​

通过 files= 发送 multipart 文件,配合 data=QueryParams(...) 添加普通或重复字段。 Req 自动生成 boundary 和 Content-Type;手工指定 Content-Type 时必须包含合法匹配的 multipart boundary。 files 不能与 content、json、body 同时使用。

def __init__(
out self, name: String, path: String, *,
filename: Optional[String] = None,
content_type: String = "application/octet-stream",
) raises HTTPError

def __init__(
out self, name: String, body: RequestBody, *,
filename: String = "upload",
content_type: String = "application/octet-stream",
) raises HTTPError

UploadFile.from_bytes(
name: String, content: Bytes, *,
filename: String = "upload",
content_type: String = "application/octet-stream",
) raises HTTPError -> UploadFile

UploadFile(name, path) 默认使用文件路径的最后一段作为 filename。 公开字段为 name、filename、content_type、body。

import req


def main() raises:
var files = List[req.UploadFile]()
files.append(req.UploadFile.from_bytes(
"file", req.encode_utf8("hello\n"),
filename="hello.txt", content_type="text/plain",
))
var fields = req.QueryParams("tag=mojo&tag=http")
var response = req.post(
"https://httpbin.org/post", data=fields, files=files,
)
response.raise_for_status()
print(response.status_code)

307/308 重定向保留请求体,要求可重放数据源;重放已消费的一次性请求体会抛出 StreamConsumed。 改为 GET 的重定向会移除请求体。上传支持 HTTP/1.1 和 HTTP/2。