使用win32com WinHTTP发送带NT认证的Form-Data POST请求(含文件)问题
How to Send NT-Authenticated Multipart/Form-Data POST with WinHTTP in Python
Let's fix your issue step by step—your core problem here is misunderstanding how multipart/form-data works with WinHTTP, and trying to use JSON where it doesn't belong. Here's what you need to do:
First, Why Your Current Code Fails
- JSON Serialization Error: You're trying to use
json.dumps()on a dictionary containing binary file data (fromrbmode). JSON can't handle raw bytes, so this will always throw an error. - Text Mode File Error: Opening a PDF with
r(text mode) tries to decode the binary content as a string, which fails because PDFs aren't plain text—you must userbmode for binary files.
WinHTTP doesn't automatically handle multipart/form-data like the requests library does, so you need to manually construct the request body with proper boundaries and formatting.
Solution: Manually Construct Multipart/Form-Data Request
Here's a complete working example that handles the file upload and keeps the automatic NT authentication:
import win32com.client import os import random import string def generate_boundary(): # Generate a random boundary string to separate form parts return '----WinHTTPPartBoundary' + ''.join(random.choices(string.ascii_letters + string.digits, k=16)) # Configuration url = "YOUR_TARGET_URL_HERE" file_path = r'C:\filename.pdf' dataset_id = 9 date_str = "2018-04-16" # Step 1: Generate boundary boundary = generate_boundary() # Step 2: Build multipart form parts form_parts = [] # Add regular form fields form_parts.append(f'--{boundary}\r\n'.encode('utf-8')) form_parts.append(b'Content-Disposition: form-data; name="datasetid"\r\n\r\n') form_parts.append(f'{dataset_id}\r\n'.encode('utf-8')) form_parts.append(f'--{boundary}\r\n'.encode('utf-8')) form_parts.append(b'Content-Disposition: form-data; name="date"\r\n\r\n') form_parts.append(f'{date_str}\r\n'.encode('utf-8')) # Add file part file_name = os.path.basename(file_path) form_parts.append(f'--{boundary}\r\n'.encode('utf-8')) form_parts.append(f'Content-Disposition: form-data; name="file"; filename="{file_name}"\r\n'.encode('utf-8')) form_parts.append(b'Content-Type: application/pdf\r\n\r\n') # Use correct MIME type for your file with open(file_path, 'rb') as f: form_parts.append(f.read()) form_parts.append(b'\r\n') # Add closing boundary form_parts.append(f'--{boundary}--\r\n'.encode('utf-8')) # Combine all parts into a single request body request_body = b''.join(form_parts) # Step 3: Send the request with automatic NT authentication h = win32com.client.Dispatch('WinHTTP.WinHTTPRequest.5.1') h.SetAutoLogonPolicy(0) # This enables automatic NTLM/Kerberos auth using current user credentials h.Open('POST', url, False) # Set correct Content-Type header with boundary h.SetRequestHeader('Content-Type', f'multipart/form-data; boundary={boundary}') # Send the raw binary request body h.Send(request_body) # Check response print(f"Status: {h.Status} {h.StatusText}") print("Response:", h.ResponseText)
Key Details Explained
- Boundary String: This is a unique separator that tells the server where one form field ends and the next begins. We generate a random one to avoid conflicts with content in your file or fields.
- Multipart Format: Each field (including the file) is wrapped with the boundary, followed by headers describing the field, then the content. The file part includes the filename and correct MIME type (adjust this if you're uploading a different file type, like
image/pngfor images). - Automatic NT Authentication:
SetAutoLogonPolicy(0)tells WinHTTP to use the current Windows user's credentials for NTLM or Kerberos authentication—no manual username/password required, which matches your requirement. - Binary Handling: We read the file in
rbmode to keep it as raw bytes, and combine all parts into a single binary request body that WinHTTP can send correctly.
Troubleshooting Tips
- If you get authentication errors, double-check that the current user has permission to access the target URL (WinHTTP uses your logged-in user's context).
- Verify the MIME type for your file—using the wrong type might cause the server to reject the upload.
- Ensure the boundary string in the
Content-Typeheader exactly matches the one used in the request body.
内容的提问来源于stack exchange,提问作者Lim Min
相关产品推荐
相关产品推荐

