如何用pyCurl复用连接串行上传多文件至WebDAV服务器
问题描述
目前使用pyCurl将base64字符串格式的单个文件上传至WebDAV服务器,现有代码如下:
def fileupload(url, filename, filedata, upload_user, upload_pw): filedata = base64.b64decode(filedata).decode('ascii', 'ignore') # Initialize pycurl c = pycurl.Curl() url = url + filename c.setopt(pycurl.URL, url) c.setopt(pycurl.UPLOAD, 1) c.setopt(pycurl.READFUNCTION, StringIO(filedata).read) c.setopt(pycurl.CONNECTTIMEOUT, 5) c.setopt(pycurl.TIMEOUT, 20) c.setopt(pycurl.SSL_VERIFYPEER, 1) c.setopt(pycurl.SSL_VERIFYHOST, 2) c.setopt(pycurl.CAINFO, "ca.pem") c.setopt(pycurl.USERPWD, upload_user + ":" + upload_pw) # Set size of file to be uploaded. filesize = len(filedata) c.setopt(pycurl.INFILESIZE, filesize) # Start transfer logPes.debug('Uploading file %s to url %s' % (filename, url)) try: c.perform() # Check result of transfer if c.getinfo(pycurl.HTTP_CODE) == 201: c.close() logPes.info('Fileupload successful') return True else: logPes.error('Fileupload NOT successful. Error code {0}.'.format(c.getinfo(pycurl.HTTP_CODE))) c.close() return False except pycurl.error as error: logPes.error('Fileupload: {0}'.format(error.args[1])) return False
多次调用该函数上传多文件时,会反复建立并关闭连接。想了解:
- 是否可通过pyCurl复用同一连接串行上传多文件?
- pycurl.CurlMulti是否适用?它是否复用连接,是串行还是异步执行?服务器性能较弱,希望以此减少负载。
解答
一、复用单个Curl连接串行上传多文件
完全可以复用同一个pycurl.Curl实例来串行上传多个文件,这是减少连接建立开销、降低弱服务器负载的最优方案。
修改思路
- 仅初始化一次
Curl实例,设置通用选项(超时、SSL验证、用户密码等),避免重复创建销毁连接。 - 每次上传单个文件时,仅更新需要变更的选项:目标URL、文件读取函数、文件大小。
- 所有文件上传完成后,再统一关闭
Curl实例。
示例代码
import pycurl from io import StringIO import base64 import logging logPes = logging.getLogger(__name__) def init_curl_handle(base_url, upload_user, upload_pw): # 初始化一次Curl实例,配置通用参数 curl = pycurl.Curl() curl.setopt(pycurl.CONNECTTIMEOUT, 5) curl.setopt(pycurl.TIMEOUT, 20) curl.setopt(pycurl.SSL_VERIFYPEER, 1) curl.setopt(pycurl.SSL_VERIFYHOST, 2) curl.setopt(pycurl.CAINFO, "ca.pem") curl.setopt(pycurl.USERPWD, f"{upload_user}:{upload_pw}") curl.setopt(pycurl.UPLOAD, 1) # 固定开启上传模式 return curl def upload_single_file(curl_handle, base_url, filename, filedata): # 解码base64文件数据 filedata = base64.b64decode(filedata).decode('ascii', 'ignore') target_url = base_url + filename # 更新本次上传的专属参数 curl_handle.setopt(pycurl.URL, target_url) curl_handle.setopt(pycurl.READFUNCTION, StringIO(filedata).read) curl_handle.setopt(pycurl.INFILESIZE, len(filedata)) logPes.debug('Uploading file %s to url %s' % (filename, target_url)) try: curl_handle.perform() http_code = curl_handle.getinfo(pycurl.HTTP_CODE) if http_code == 201: logPes.info('Fileupload successful: %s' % filename) return True else: logPes.error('Fileupload failed for %s. Error code: %d' % (filename, http_code)) return False except pycurl.error as error: logPes.error('Fileupload error for %s: %s' % (filename, error.args[1])) return False # 使用示例 if __name__ == "__main__": base_webdav_url = "https://your-webdav-server.com/" user = "your-username" password = "your-password" # 初始化一次连接 curl = init_curl_handle(base_webdav_url, user, password) # 待上传文件列表(文件名+base64数据) upload_tasks = [ ("doc1.txt", "base64-encoded-data-1"), ("image1.jpg", "base64-encoded-data-2"), # 更多文件... ] # 串行上传所有文件 for filename, filedata in upload_tasks: upload_single_file(curl, base_webdav_url, filename, filedata) # 所有上传完成后关闭连接 curl.close()
关键说明
- pycurl默认支持HTTP/1.1的持久连接(Keep-Alive),同一个
Curl实例多次调用perform()时,会自动复用已建立的连接,无需额外配置。 - 若某次上传出现连接中断等严重错误,可考虑重新初始化
Curl实例,但大部分场景下无需额外处理。
二、关于pycurl.CurlMulti的适用场景
CurlMulti并不适合你的弱服务器场景,具体说明如下:
- 执行方式:CurlMulti是异步并发执行多个请求,会同时发起多个上传任务,反而会增加服务器的负载,与你降低服务器压力的需求相悖。
- 连接复用:CurlMulti内部维护连接池,支持连接复用,但前提是并发执行,对性能较弱的服务器不友好。
- 适用场景:仅当服务器性能充足、需要提升上传效率时,CurlMulti才是合适的选择;你的场景更适合用单个
Curl实例串行上传。
内容的提问来源于stack exchange,提问作者nico
相关产品推荐
相关产品推荐

