পাইথন স্ক্রিপ্ট থেকে POST ব্যবহার করে ফাইল প্রেরণ করুন


উত্তর:


214

থেকে: https://requests.readthedocs.io/en/latest/user/quickstart/#post-a-multpart-encoded-file

অনুরোধগুলি মাল্টিপার্ট-এনকোডযুক্ত ফাইলগুলি আপলোড করা খুব সহজ করে তোলে:

with open('report.xls', 'rb') as f:
    r = requests.post('http://httpbin.org/post', files={'report.xls': f})

এটাই. আমি রসিকতা করছি না - এটি কোডের এক লাইন। ফাইলটি পাঠানো হয়েছিল। আসুন পরীক্ষা করে দেখুন:

>>> 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": ""
}

2
আমি একই জিনিসটি চেষ্টা করছি & যদি ফাইলের আকার ~ 1.5 মেগাবাইটের চেয়ে কম হয় তবে এটি কাজ করছে। অন্যথায় এটি একটি ত্রুটি নিক্ষেপ .. দয়া করে এখানে দেখুন
নিকস জৈন

1
আমি যা চেষ্টা করছি তা হ'ল অনুরোধটি ব্যবহার করে কোনও সাইটে লগইন করা যা আমি সফলভাবে করেছি তবে এখন আমি লগ ইন করার পরে একটি ভিডিও আপলোড করতে চাই এবং জমা দেওয়ার আগে ফর্মটির আলাদা ক্ষেত্র রয়েছে। সুতরাং ভিডিওর বিবরণ, ভিডিওর শিরোনাম ইত্যাদির মতো কীভাবে আমি সেই মানগুলি পাস করব
তারাগুরুং

15
আপনি সম্ভবত with open('report.xls', 'rb') as f: r = requests.post('http://httpbin.org/post', files={'report.xls': f})পরিবর্তে এটি করতে চান , তাই এটি খোলার পরে ফাইলটি আবার বন্ধ করে দেয়।
Hjulle

3
তাই না? যেহেতু অনুরোধগুলি প্রেরণ করা এত সহজ?
পালশ

1
ফাইলটি বন্ধ রয়েছে তা নিশ্চিত করতে প্রাসঙ্গিক ব্যবস্থাপক ব্যবহার করার জন্য হজুলের পরামর্শ অন্তর্ভুক্ত করার জন্য এই উত্তরটি আপডেট করা উচিত।
বমোরান

28

হ্যাঁ. আপনি urllib2মডিউলটি ব্যবহার করবেন এবং multipart/form-dataসামগ্রী প্রকারটি ব্যবহার করে এনকোড করুন । আপনাকে শুরু করার জন্য এখানে কিছু নমুনা কোড দেওয়া হয়েছে - এটি কেবল ফাইল আপলোডিংয়ের চেয়ে কিছুটা বেশি, তবে আপনার এটি পড়তে এবং এটি কীভাবে কাজ করে তা দেখতে সক্ষম হওয়া উচিত:

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!')

1
পাইথন ২.6. On এ আমি উইন্ডোজটিতে এই কোডটি ব্যবহার করার সময় মাল্টিপার্ট বাউন্ডারি পার্সিংয়ে একটি ত্রুটি পেয়েছিলাম। আমি এ বিষয়ে আলোচনা string.ascii_letters করার string.letters থেকে পরিবর্তন করতে হয়েছে stackoverflow.com/questions/2823316/... এটির জন্য কাজ করতে। সীমানা সম্পর্কে প্রয়োজনীয়তা এখানে আলোচনা করা হয়েছে: stackoverflow.com/questions/147451/…
amit

রান_আপলোড ({'সার্ভার': '', 'থ্রেড': ''}, পাথস = ['/ পাথ / টু / ফাইল.txt']) কল করার ফলে এই লাইনে ত্রুটি দেখা দেয়: আপলোড_ফাইলে (পাথ) কারণ "আপলোড ফাইল" প্রয়োজন 3 টি প্যারামিটার তাই আমি এটির পরিবর্তে এই লাইনটি আপলোড_ ফাইল (পথ, 1, 1)
রেডিয়ান

4

একমাত্র জিনিস যা আপনাকে সরাসরি কোনও ফাইল বস্তুর উপর urlopen ব্যবহার করা থেকে বিরত করে তা হ'ল বিল্টিন ফাইল অবজেক্টটিতে লেন সংজ্ঞা থাকে না। একটি সহজ উপায় হ'ল একটি সাবক্লাস তৈরি করা, যা সঠিক ফাইলের সাথে urlopen সরবরাহ করে। আমি নীচের ফাইলটিতে সামগ্রী-প্রকারের শিরোনামটিও সংশোধন করেছি।

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

@ আরবার্ট আমি পাইথন 2.7 তে আপনার কোডটি পরীক্ষা করি তবে এটি কার্যকর হয় না। urlopen (অনুরোধ (ইউআরএল, দ্য ফাইলে, ...)) কেবলমাত্র একটি সাধারণ পোস্টের মতো ফাইলের সামগ্রীকে এনকোড করে তবে সঠিক ফর্ম ক্ষেত্রটি নির্দিষ্ট করতে পারে না। আমি এমনকি ভেরিয়েন্ট urlopen (ইউআরএল, ইউরেলকোড ({'সার্ভারসাইড_ফিল্ড_নাম': এনহ্যান্সডফাইলে ('আমার_ফিল.টেক্সট')})) চেষ্টা করে দেখি, এটি একটি ফাইল ওপেন করে (অবশ্যই!) <ওপেন ফাইল 'my_file.txt' হিসাবে ভুল বিষয়বস্তু সহ, মোড 'আর' 0x00D6B718> এ। আমি কি কিছু রেখে গেলাম?
রায়লুও

উত্তর করার জন্য ধন্যবাদ . উপরের কোডটি ব্যবহার করে আমি ওয়েবসারভারে পিটি অনুরোধ ব্যবহার করে ২.২ গিগাবাইট কাঁচা চিত্র ফাইলটি স্থানান্তর করেছি।
অক্ষয় পাতিল

4

দেখে মনে হচ্ছে পাইথন অনুরোধগুলি অত্যন্ত বড় মাল্টি-পার্ট ফাইলগুলি পরিচালনা করে না।

ডকুমেন্টেশন আপনাকে সন্ধান করার পরামর্শ দেয় requests-toolbelt

তাদের ডকুমেন্টেশন থেকে প্রাসঙ্গিক পৃষ্ঠা এখানে's


2

ক্রিস অ্যাটলির পোস্টার লাইব্রেরি এটির জন্য সত্যই ভাল কাজ করে (বিশেষত সুবিধার ফাংশন poster.encode.multipart_encode())। বোনাস হিসাবে, এটি একটি সম্পূর্ণ ফাইলকে মেমরিতে লোড না করে বড় ফাইলগুলির স্ট্রিমিং সমর্থন করে। আরও দেখুন পাইথন ইস্যু 3244


2

আমি জ্যাঙ্গো রেস্ট এপি এবং এটির জন্য আমার কাজ করার পরীক্ষা করার চেষ্টা করছি:

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
এই কোডটি একটি মেমরি ফাঁস দেয় - আপনি close()কোনও ফাইল ভুলে গেছেন ।
চিফির

0

আপনি উদাহরণ সহ httplib2 এ একবার দেখতে চান । আমি দেখতে পাই যে বিল্ট-ইন এইচটিটিপি মডিউলগুলি ব্যবহারের চেয়ে httplib2 ব্যবহার করা আরও সংক্ষিপ্ত।


2
ফাইল আপলোডগুলি কীভাবে মোকাবেলা করতে হয় তার কোনও উদাহরণ নেই।
dland

লিঙ্কটি পুরানো + কোনও অন্তর্নিহিত উদাহরণ নেই।
jlr

3
এটি এর পরে github.com/httplib2/httplib2 এ চলে গেছে । অন্যদিকে, আজকাল আমি সম্ভবত requestsপরিবর্তে সুপারিশ করব ।
পিডিসি

0
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()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.