Gibt es eine Möglichkeit, eine Datei mithilfe von POST aus einem Python-Skript zu senden?Datei mit POST aus einem Python-Skript senden
Antwort
Ja. Sie würden das Modul urllib2
verwenden und mit dem Inhaltstyp multipart/form-data
codieren. Hier ist ein Beispielcode für den Anfang - es ist ein bisschen mehr als nur Hochladen der Datei, aber Sie sollten durch sie in der Lage zu lesen und sehen, wie es funktioniert:
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!')
Chris Atlee poster Bibliothek funktioniert wirklich gut für diese (vor allem die Komfortfunktion poster.encode.multipart_encode()
). Als Bonus unterstützt es das Streamen großer Dateien, ohne eine ganze Datei in den Speicher zu laden. Siehe auch Python issue 3244.
Die einzige Sache, die Sie davon abhält, urlopen direkt auf einem Dateiobjekt zu verwenden, ist die Tatsache, dass das eingebaute Dateiobjekt keine len Definition hat. Eine einfache Möglichkeit besteht darin, eine Unterklasse zu erstellen, die urlopen mit der korrekten Datei versorgt. Ich habe auch den Content-Type-Header in der Datei unten geändert.
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 Ich teste deinen Code in Python2.7, aber es funktioniert nicht. urlopen (Request (THEURL, thefile, ...)) kodiert, lediglich den Inhalt der Datei, als ob eine normale Post, aber das richtige Formularfeld nicht angeben kann. Ich versuche sogar Variante urlopen (THEURL, urlencode ({ 'serverside_field_name': EnhancedFile ('my_file.txt')})), lädt er eine Datei aber (natürlich!) Mit falschem Inhalt als
Danke für die Antwort. Unter Verwendung des obigen Codes hatte ich eine 2,2-GB-Rohbilddatei unter Verwendung der PUT-Anforderung in den Webserver übertragen. –
Von http://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file
Anfragen macht es sehr einfach, Multipart-kodierte Dateien hochladen:
>>> with open('report.xls', 'rb') as f: r = requests.post('http://httpbin.org/post', files={'report.xls': f})
Das ist es. Ich mache keine Witze - das ist eine Codezeile. Die Datei wurde gesendet. Lassen Sie uns überprüfen:
>>> 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": ""
}
Ich versuche das gleiche, und es funktioniert gut, wenn die Dateigröße weniger als ~ 1,5 MB ist. seine sonst einen Fehler werfen .. bitte Blick auf [hier] haben (http://stackoverflow.com/questions/20217348/requests-post-files-upload-large-file-more-than-1-5-mb-python). –
, was zu einem gewissen Website mit Wunsch zu tun versucht, ist Login, die ich erfolgreich getan habe, aber jetzt will ich nach der Anmeldung ein Video hochladen und die Form hat ein anderen Felder vor der Vorlage ausgefüllt werden. Also, wie soll ich diese Werte wie Videos Beschreibung passieren, Videos Titel etc – TaraGurung
Sie würden vermutlich 'mit offenem tun wollen ('Report.xls', 'rb') als f: r = requests.post ('http: // httpbin.org/post ', files = {' report.xls ': f}) 'stattdessen, so schließt es die Datei nach dem Öffnen wieder. – Hjulle
Sieht aus wie Python-Anfragen nicht behandelt extrem große mehrteilige Dateien.
Die Dokumentation empfiehlt Ihnen, in requests-toolbelt
zu schauen.
Here's the pertinent page aus ihrer Dokumentation.
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()
ich für mich Rest api und seine Arbeits zu testen versuchen django:
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. Senden Sie Datei mit POST von einem Python-Skript
- 2. Datei in POST Anfrage mit Windows Phone 7 senden
- 3. Datei zusammen mit Formulardaten über Ajax-Post senden
- 4. Senden Sie Datei + Parameter in Post-Anfrage
- 5. Senden von Multipart-Datei als POST-Parameter mit RestTemplate-Anfragen
- 6. Cocoa POST-Anfrage mit Datei
- 7. POST Anfrage mit Netcat senden
- 8. Python senden POST mit Header
- 9. Per Post mit Restangular senden
- 10. Post-XML-Datei mit Python
- 11. Senden von Bildern mit Http Post
- 12. So senden Sie eine Post-Anfrage mit einem Web-Browser
- 13. Wie senden Sie zwei Post-Parameter mit einem Button-Tag?
- 14. So senden Sie Post-Informationen mit in einem window.location.replace Code
- 15. Wie Array PHP mit jQuery $ .post senden()
- 16. mit Bildparametern an einem anderen PHP-Datei senden
- 17. JQuery Senden einer json mit Post
- 18. Senden von HTTP-Post-Request mit Android
- 19. senden json und Datei mit Retrofit2
- 20. Ajax Post mit einer Datei zurückgeben
- 21. senden "POST" Liste von int
- 22. NanoHTTPD: Laden Sie eine Datei mit einem HTML-Formular (POST)
- 23. Senden einer Post-Anfrage mit net/http
- 24. Java - Senden einer Post-Anfrage mit HtmlUnit
- 25. Problem beim Senden eines POST mit Java
- 26. Post-Daten mit PHP senden dann umleiten
- 27. So senden Sie POST FromData mit Angular2
- 28. Cookie Senden mit http Post android
- 29. IE senden POST statt GET mit $ .get
- 30. Wie kann ich eine Datei in einer POST-Anfrage senden?
Auf Python 2.6.6 Ich war einen Fehler in Mehrteiliger Grenze Parsing bekommen, während Sie diesen Code auf Windows. Ich musste von string.letters zu string.ascii_letters wechseln, wie in http://stackoverflow.com/questions/2823316/generate-a-random-letter-in-python/2823331#2823331 beschrieben, damit dies funktioniert. Die Randbedingung wird hier erläutert: http://stackoverflow.com/questions/147451/what-are-valid-characters-for-creating-a-multipart-form-boundary/147467#147467 –
Aufruf run_upload ({' Server ':', 'Thread': ''}, Pfade = ['/ Pfad/zu/Datei.txt']) verursacht Fehler in dieser Zeile: upload_file (Pfad) , da "Datei hochladen" 3 Parameter erfordert , also ersetze ich es mit dieser Zeile upload_file (Pfad, 1, 1) – Radian