如何使用请求库将数据发送到服务器?

时间:2017-01-20 20:31:10

标签: python http server binary python-requests

工作过程是我向服务器发送票证,服务器将回复我需要的信息。例如,

import requests
URL = "https://ssl.XXX.com/sql_v5i.php"
Ticket = {"A":"1","B":"2"}  # a dictionary
ticket_post = requests.post(URL, data=Ticket)
print ticket__post.text

但是如何一次性发送带有"A":"1", "B":"2"和二进制数据(仅包含数据和无密钥)的票证?如果我只发送二进制数据,我可以使用"文件"。但是如何将所有这些信息一起发送到服务器?直观地说,它会更像这样(但显然它不会起作用):

import requests
URL = "https://ssl.XXX.com/sql_v5i.php"
Ticket = {"A":"1","B":"2","1010110111100110...101010"} 
ticket_post = requests.post(URL, data=Ticket)
print ticket__post.text

为了完成这项任务,有一段PHP工作:

<?php

$BASE_SERVER_URL="https://ssl.XXX.com/sql_v5i.php"
$TICKET = array(
          'fn' => 'ticket',
          'testid' => '2'
          ... # And many other key-value pair in the TICKET array
          );    

class DataStreamer{
  private $data;
  private $pos;

function __construct($data) {
  $this->data = $data;
  $this->pos = 0;
}

function stream_function($handle, $fd, $count){
$res = substr($this->data, $this->pos, $count);
$this->pos += strlen($res);
return $res;
}
}

function sendTicketToServer($data) {
global $TICKET, $BASE_SERVER_URL; # TICKET is an array stores ticket           
                                  #  information in php
$ret = array(true);  
$postFields = "";
foreach ($TICKET as $name => $val)
    $postFields = (empty($postFields) ? "" :  "${postFields}&") ."${name}=" . urlencode($val); 

$ch = curl_init(); 

curl_setopt( $ch, CURLOPT_POST, true );  
curl_setopt( $ch, CURLOPT_URL, "${BASE_SERVER_URL}?" . $postFields );  
                                        # add key-value pairs
curl_setopt( $ch, CURLOPT_VERBOSE, false );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );

 if (!empty($data)) { # data is the binary string , add binary string
    curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true); 
    curl_setopt( $ch, CURLOPT_HEADER, true); 
    curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-type: application/octet-stream', 'Content-length: ' . strlen($data))); 
    curl_setopt( $ch, CURLOPT_READFUNCTION, array(new DataStreamer($data), "stream_function")); 
    } else {
    curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-type: application/octet-stream', 'Content-length: 0')); 
}

$resp = curl_exec($ch);
$code=curl_getinfo($ch, CURLINFO_HTTP_CODE);
if( $resp === FALSE || $code !== 200 ) {
    echo "!!!!! Failed to get connection from the server. Code:    $code\n";
    return array(ERR_NO_SERVER_CONNECTION."000");
}

curl_close($ch); 
return $ret;

如何在Python中执行相同操作(使用请求或不使用请求)。

2 个答案:

答案 0 :(得分:1)

这不是请求模块的问题。如果我们认为您可以使用请求发送任何类型的数据结构,则必须找到允许您使用密钥引用数据的数据结构,如果未提供密钥,则会返回二进制数据作为默认值值。 不幸的是python词典不允许这样做,因为有一个共同的协议,在字典中我们使用键引用数据。

编辑:您可以从使用dict的实际实现开始

class kldict(dict):
    def __init__(self, default, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))
        self.default = default

    def update(self, *args, **kwargs):
        for k, v in dict(*args, **kwargs).iteritems():
            self.store[self.__keytransform__(k)] = v

    def __setitem__(self, key, value):
        self.store[self.__keytransform__(key)] = value

    def __delitem__(self, key):
        del self.store[self.__keytransform__(key)]

    def __getitem__(self, key=None):
        if key:
            return self.store[self.__keytransform__(key)]
        else:
            return self.default

    def __len__(self):
        return len(self.store)

    def __keytransform__(self, key):
        return key

    def __repr__(self):
        return self.default

示例用法如下:

var = kldict('0111010110110', {'C': 'D'})
var['B'] = 'G'
print(var['B'])
print(var['C'])
print(var[None])
print(var)

结果是:

G
D
0111010110110
0111010110110

答案 1 :(得分:0)

这个问题的细节太少,无法准确回答,但无论如何这都是尝试。

似乎好像你想将这样格式化的数据发送到服务器:

// get status of button
var status = button.get(); // returns "true" or "false"

如果是这种情况,请求已经没有方式为您执行此操作。它只处理最常见的用例。但是,假设这是您想要的格式,您必须自己提供字符串,如下所示:

button.on('pressed', function() {
    // call this function every time when button is pressed
});

button.on('released', function() {
    // call this function every time when button is released
});

也就是说,如果您未指定A=1&B=2&1010110111100110...101010 ,则网站可能无法理解您发送的数据。使用此表单时,可能也需要传递

import urllib.parse

import requests

data = urllib.parse.urlencode({'A': '1', 'B': '2'}) + '1010110111100110...101010'
response = requests.post(url, data=data)

Content-Type。我使用headers={'Content-Type': '...'} ,因为我不清楚该网站预期的requests.post

相关问题