Có cách nào để gửi tệp bằng POST từ tập lệnh Python không?Gửi tệp bằng POST từ tập lệnh Python
Trả lời
Có. Bạn sẽ sử dụng mô-đun urllib2
và mã hóa bằng loại nội dung multipart/form-data
. Dưới đây là một số mẫu mã để giúp bạn bắt đầu - đó là nhiều hơn một chút so với chỉ nộp tải lên, nhưng bạn sẽ có thể đọc qua nó và xem làm thế nào nó hoạt động:
user_agent = "image uploader"
default_message = "Image $current of $total"
import logging
import os
from os.path import abspath, isabs, isdir, isfile, join
import random
import string
import sys
import mimetypes
import urllib2
import httplib
import time
import re
def random_string (length):
return ''.join (random.choice (string.letters) for ii in range (length + 1))
def encode_multipart_data (data, files):
boundary = random_string (30)
def get_content_type (filename):
return mimetypes.guess_type (filename)[0] or 'application/octet-stream'
def encode_field (field_name):
return ('--' + boundary,
'Content-Disposition: form-data; name="%s"' % field_name,
'', str (data [field_name]))
def encode_file (field_name):
filename = files [field_name]
return ('--' + boundary,
'Content-Disposition: form-data; name="%s"; filename="%s"' % (field_name, filename),
'Content-Type: %s' % get_content_type(filename),
'', open (filename, 'rb').read())
lines = []
for name in data:
lines.extend (encode_field (name))
for name in files:
lines.extend (encode_file (name))
lines.extend (('--%s--' % boundary, ''))
body = '\r\n'.join (lines)
headers = {'content-type': 'multipart/form-data; boundary=' + boundary,
'content-length': str (len (body))}
return body, headers
def send_post (url, data, files):
req = urllib2.Request (url)
connection = httplib.HTTPConnection (req.get_host())
connection.request ('POST', req.get_selector(),
*encode_multipart_data (data, files))
response = connection.getresponse()
logging.debug ('response = %s', response.read())
logging.debug ('Code: %s %s', response.status, response.reason)
def make_upload_file (server, thread, delay = 15, message = None,
username = None, email = None, password = None):
delay = max (int (delay or '0'), 15)
def upload_file (path, current, total):
assert isabs (path)
assert isfile (path)
logging.debug ('Uploading %r to %r', path, server)
message_template = string.Template (message or default_message)
data = {'MAX_FILE_SIZE': '3145728',
'sub': '',
'mode': 'regist',
'com': message_template.safe_substitute (current = current, total = total),
'resto': thread,
'name': username or '',
'email': email or '',
'pwd': password or random_string (20),}
files = {'upfile': path}
send_post (server, data, files)
logging.info ('Uploaded %r', path)
rand_delay = random.randint (delay, delay + 5)
logging.debug ('Sleeping for %.2f seconds------------------------------\n\n', rand_delay)
time.sleep (rand_delay)
return upload_file
def upload_directory (path, upload_file):
assert isabs (path)
assert isdir (path)
matching_filenames = []
file_matcher = re.compile (r'\.(?:jpe?g|gif|png)$', re.IGNORECASE)
for dirpath, dirnames, filenames in os.walk (path):
for name in filenames:
file_path = join (dirpath, name)
logging.debug ('Testing file_path %r', file_path)
if file_matcher.search (file_path):
matching_filenames.append (file_path)
else:
logging.info ('Ignoring non-image file %r', path)
total_count = len (matching_filenames)
for index, file_path in enumerate (matching_filenames):
upload_file (file_path, index + 1, total_count)
def run_upload (options, paths):
upload_file = make_upload_file (**options)
for arg in paths:
path = abspath (arg)
if isdir (path):
upload_directory (path, upload_file)
elif isfile (path):
upload_file (path)
else:
logging.error ('No such path: %r' % path)
logging.info ('Done!')
Thư viện của Chris Atlee poster hoạt động thực sự tốt cho điều này (đặc biệt là chức năng tiện lợi poster.encode.multipart_encode()
). Là một phần thưởng, nó hỗ trợ phát trực tuyến các tệp lớn mà không cần tải toàn bộ tệp vào bộ nhớ. Xem thêm Python issue 3244.
Điều duy nhất ngăn bạn sử dụng urlopen trực tiếp trên đối tượng tệp là thực tế là đối tượng tệp được dựng sẵn thiếu định nghĩa len. Một cách đơn giản là tạo một lớp con, cung cấp urlopen với tệp chính xác. Tôi cũng đã sửa đổi tiêu đề Loại Nội dung trong tệp bên dưới.
import os
import urllib2
class EnhancedFile(file):
def __init__(self, *args, **keyws):
file.__init__(self, *args, **keyws)
def __len__(self):
return int(os.fstat(self.fileno())[6])
theFile = EnhancedFile('a.xml', 'r')
theUrl = "http://example.com/abcde"
theHeaders= {'Content-Type': 'text/xml'}
theRequest = urllib2.Request(theUrl, theFile, theHeaders)
response = urllib2.urlopen(theRequest)
theFile.close()
for line in response:
print line
@robert Tôi kiểm tra mã của bạn bằng Python2.7 nhưng nó không hoạt động. urlopen (Yêu cầu (theUrl, theFile, ...)) chỉ mã hóa nội dung của tệp như một bài đăng bình thường nhưng không thể chỉ định trường biểu mẫu chính xác. Tôi thậm chí thử biến thể urlopen (theUrl, urlencode ({'serverside_field_name': EnhancedFile ('my_file.txt')})), nó tải lên một tệp nhưng (tất nhiên!) Với nội dung không đúng như
Cảm ơn câu trả lời. Bằng cách sử dụng đoạn mã trên, tôi đã chuyển tập tin hình ảnh thô 2,2 GB bằng cách sử dụng yêu cầu PUT vào máy chủ web. –
Từ http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file
Các yêu cầu làm cho nó rất đơn giản để upload file dung nhiều mã hóa:
>>> with open('report.xls', 'rb') as f: r = requests.post('http://httpbin.org/post', files={'report.xls': f})
Vậy là xong. Tôi không nói đùa - đây là một dòng mã. Tệp đã được gửi. Hãy kiểm tra:
>>> r.text
{
"origin": "179.13.100.4",
"files": {
"report.xls": "<censored...binary...data>"
},
"form": {},
"url": "http://httpbin.org/post",
"args": {},
"headers": {
"Content-Length": "3196",
"Accept-Encoding": "identity, deflate, compress, gzip",
"Accept": "*/*",
"User-Agent": "python-requests/0.8.0",
"Host": "httpbin.org:80",
"Content-Type": "multipart/form-data; boundary=127.0.0.1.502.21746.1321131593.786.1"
},
"data": ""
}
Tôi đang thử điều tương tự và hoạt động tốt nếu kích thước tệp nhỏ hơn ~ 1,5 MB. khác ném một lỗi của nó .. xin vui lòng xem [ở đây] (http://stackoverflow.com/questions/20217348/requests-post-files-upload-large-file-more-than-1-5-mb-python). –
những gì cố gắng làm là đăng nhập vào một số trang web bằng cách yêu cầu mà tôi đã thực hiện thành công nhưng bây giờ tôi muốn tải lên video sau khi đăng nhập và biểu mẫu có các trường khác nhau sẽ được điền trước khi gửi. Vì vậy, làm thế nào tôi nên vượt qua những giá trị như video mô tả, tiêu đề video vv – TaraGurung
Bạn có thể muốn làm 'với mở ('report.xls', 'rb') là f: r = requests.post ('http: // Thay vào đó, httpbin.org/post ', files = {' report.xls ': f}) 'sẽ đóng lại tệp sau khi mở. – Hjulle
Có vẻ như yêu cầu python không xử lý các tệp nhiều phần cực lớn.
Tài liệu đề xuất bạn xem xét requests-toolbelt
.
Here's the pertinent page từ tài liệu của họ.
def visit_v2(device_code, camera_code):
image1 = MultipartParam.from_file("files", "/home/yuzx/1.txt")
image2 = MultipartParam.from_file("files", "/home/yuzx/2.txt")
datagen, headers = multipart_encode([('device_code', device_code), ('position', 3), ('person_data', person_data), image1, image2])
print "".join(datagen)
if server_port == 80:
port_str = ""
else:
port_str = ":%s" % (server_port,)
url_str = "http://" + server_ip + port_str + "/adopen/device/visit_v2"
headers['nothing'] = 'nothing'
request = urllib2.Request(url_str, datagen, headers)
try:
response = urllib2.urlopen(request)
resp = response.read()
print "http_status =", response.code
result = json.loads(resp)
print resp
return result
except urllib2.HTTPError, e:
print "http_status =", e.code
print e.read()
Tôi cố gắng để kiểm tra django api nghỉ ngơi và làm việc của nó cho tôi:
def test_upload_file(self):
filename = "/Users/Ranvijay/tests/test_price_matrix.csv"
data = {'file': open(filename, 'rb')}
client = APIClient()
# client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
response = client.post(reverse('price-matrix-csv'), data, format='multipart')
print response
self.assertEqual(response.status_code, status.HTTP_200_OK)
- 1. Gửi đối số từ tệp Batch tới tập lệnh Python
- 2. gửi đầu ra đến tệp từ trong tập lệnh shell
- 3. Yêu cầu Python - Dữ liệu POST từ một tệp
- 4. Python 3, urllib POST gửi
- 5. Cách tải tệp lên Google Drive bằng tập lệnh Python?
- 6. Chạy tập lệnh Python từ trang web
- 7. Mở loại tệp cụ thể bằng tập lệnh Python?
- 8. Gửi yêu cầu POST không phải ASCII bằng Python?
- 9. Cách Lọc từ tệp CSV sử dụng Tập lệnh Python
- 10. python gửi POST với tiêu đề
- 11. Gọi hàm Python từ tập lệnh shell
- 12. Gửi yêu cầu POST bằng netcat
- 13. Gửi tệp qua ổ cắm bằng Python
- 14. Gọi tập lệnh python từ crontab bằng cách kích hoạt
- 15. Chạy tập lệnh Python từ ứng dụng Cocoa bằng GCD
- 16. Gọi tập lệnh Perl từ Python
- 17. Cách tải xuống tệp từ API Drive bằng cách sử dụng tập lệnh Python
- 18. Cách gửi NSData bằng POST từ ứng dụng iOS?
- 19. Tạo tệp BAT cho tập lệnh python
- 20. gửi tệp xml tới http bằng python
- 21. Yêu cầu POST HTTP trong Tập lệnh Thiết lập Inno
- 22. PYTHON nhận tệp từ dòng lệnh
- 23. Gọi exiftool từ tập lệnh python?
- 24. Gửi một tập tin qua HTTP POST với C#
- 25. Xem những gì CURL gửi từ tập lệnh PHP
- 26. Gửi tập tin bằng cách sử dụng HTTP POST trong C#
- 27. Chạy tập lệnh php (từ xa) từ tập lệnh python (cục bộ)
- 28. iPhone gửi POST với NSURLConnection
- 29. Phân cấp tệp phù hợp để hủy gửi bằng Python
- 30. Cách gửi e-mail từ tập lệnh Python đang được chạy trên "Google App Engine"?
On python 2.6.6 tôi đã nhận được một lỗi trong ranh giới phân tích dung nhiều khi sử dụng mã này trên Windows. Tôi đã phải thay đổi từ string.letters thành string.ascii_letters như được thảo luận tại http://stackoverflow.com/questions/2823316/generate-a-random-letter-in-python/2823331#2823331 để làm việc này. Yêu cầu về ranh giới được thảo luận tại đây: http://stackoverflow.com/questions/147451/what-are-valid-characters-for-creating-a-multipart-form-boundary/147467#147467 –
gọi run_upload ({' server ':' ',' thread ':' '}, paths = ['/path/to/file.txt ']) gây ra lỗi trong dòng này: upload_file (đường dẫn) vì "tệp tải lên" yêu cầu 3 tham số vì vậy tôi thay thế bằng dòng này upload_file (đường dẫn, 1, 1) – Radian