使用urllib提交multipart表单时POST请求异常转为GET的问题求助
问题排查与修复方案
嘿,我来帮你找找问题出在哪——你的脚本有几个关键错误,导致POST请求没按预期触发,反而返回了原页面的HTML:
1. 请求URL搞错了
你把请求发到了原表单页面https://accuracy3.html,但表单的action属性明确指向了accuracy-upload3,这才是处理文件上传的后端接口地址。你应该把请求URL改成https://your-domain/accuracy-upload3(记得替换成实际的域名),不然只会拿到表单本身,永远得不到提交后的响应。
2. Content-Type与表单编码不匹配
表单的enctype是multipart/form-data(这是文件上传必须用的编码),但你设置的请求头是application/x-www-form-urlencoded——这种编码只适合普通键值对,没法处理文件内容。用错编码的话,后端根本识别不了你传的文件,自然不会正确处理请求。
3. 表单参数完全写错了
你构建的values字典问题很多:
- 表单文件字段的
name是human和machine,不是Human和Machine(后端只认HTML里name属性的值) id、name这些是给前端DOM用的属性,不需要作为参数传给后端value: "Submit"也没必要,提交按钮的参数不是文件上传必需的
修正后的代码示例
下面是调整后的urllib2代码,正确处理multipart/form-data编码的文件上传:
import urllib2 import mimetypes import cookielib def encode_multipart_formdata(fields, files): # 生成随机分隔符,避免和文件内容冲突 boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW' lines = [] # 处理普通字段(这里没有,可忽略) for name, value in fields.items(): lines.append('--' + boundary) lines.append(f'Content-Disposition: form-data; name="{name}"') lines.append('') lines.append(value) # 处理文件字段 for name, filename, content in files: lines.append('--' + boundary) lines.append(f'Content-Disposition: form-data; name="{name}"; filename="{filename}"') # 自动识别文件MIME类型 content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream' lines.append(f'Content-Type: {content_type}') lines.append('') lines.append(content) lines.append('--' + boundary + '--') lines.append('') return '\r\n'.join(lines), f'multipart/form-data; boundary={boundary}' # 替换为实际的后端接口URL url = "https://your-domain/accuracy-upload3" filename1 = 'human.txt' filename2 = 'machine.txt' # 安全读取文件内容 with open(filename1, 'r') as f: filedata1 = f.read() with open(filename2, 'r') as f: filedata2 = f.read() # 构造文件上传参数:(字段名, 文件名, 文件内容) files = [ ('human', filename1, filedata1), ('machine', filename2, filedata2) ] # 编码表单数据 body, content_type = encode_multipart_formdata({}, files) # 处理Appgate登录会话(必须先完成登录才能访问接口) cj = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) urllib2.install_opener(opener) # 这里需要先执行Appgate的登录流程,示例如下(替换成实际的登录接口和参数) # login_url = "https://appgate-login-domain/login" # login_payload = urllib.urlencode({'username': 'your_username', 'password': 'your_password'}) # opener.open(login_url, login_payload) # 发送文件上传请求 try: response = opener.open(url, data=body) print(response.read()) except urllib2.HTTPError as e: print(f"请求出错:状态码 {e.code}") print(e.read())
额外注意:Appgate会话处理
因为你的目标服务器需要通过Appgate登录,所以必须先完成登录流程,保存会话Cookie,之后的请求才能带上认证信息。上面的代码里已经加了CookieJar的处理逻辑,你只需要补充实际的登录请求代码即可。
内容的提问来源于stack exchange,提问作者topplethepat
相关产品推荐
相关产品推荐

