【问题标题】:How to send key-value pair and binary information together to the server using Python如何使用 Python 将键值对和二进制信息一起发送到服务器
【发布时间】:2017-06-16 01:10:52
【问题描述】:

过程是我向服务器发送票证,服务器将响应我需要的信息。例如,

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" 和二进制数据(只有数据没有密钥)的票?

为了完成这个任务,有一段 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 中做同样的事情(使用或不使用请求都可以接受)。

binary_data = "����5UU��ǚ����������h�V����������������������� ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������������������������������������������������������ ������"

【问题讨论】:

  • Pyghon 是某种库吗?
  • PHP 不会将 Ticket 作为 POST 数据发送,而是在 url 中发送 - 请参阅 "${BASE_SERVER_URL}?" . $postFields - 所以它使用 url https://ssl.XXX.com/sql_v5i.php?A=1&amp;B=2。你可以在requests 中使用params=Ticket 来做同样的事情。然后你可以data=发送二进制数据。

标签: php python post server python-requests


【解决方案1】:

PHP 示例不将 Ticket 作为 POST 数据发送,而是作为 GET 数据发送 - 这意味着在 url 中

https://ssl.XXX.com/sql_v5i.php?A=1&B=2

您可以使用params=Ticketrequests 中执行相同的操作。然后您可以使用data=files= 发送二进制数据。

我使用特殊门户httpbin.org 来测试请求,但您的门户可能需要更多工作。

import requests

url = "http://httpbin.org/post"
ticket = {"A":"1","B":"2"}
binary_data = b'hello world'

headers = {
    'Content-type': 'application/octet-stream',
}

r = requests.post(url, params=ticket, data=binary_data, headers=headers)

print('--- requests ---')
print(r.url)
print(r.request.headers)
print(r.request.body)

print('--- response ---')
print(r.text)

结果:

--- requests ---
http://httpbin.org/post?B=2&A=1
{'Content-type': 'application/octet-stream', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '11', 'User-Agent': 'python-requests/2.12.1', 'Connection': 'keep-alive', 'Accept': '*/*'}
b'hello world'
--- response ---
{
  "args": {
    "A": "1", 
    "B": "2"
  }, 
  "data": "hello world", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "11", 
    "Content-Type": "application/octet-stream", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.12.1"
  }, 
  "json": null, 
  "origin": "xxx.xxx.xxx.xxx", 
  "url": "http://httpbin.org/post?B=2&A=1"
}

您也可以使用本地代理服务器(即Charles)来比较 PHP 请求和 Python 请求。

PHP:

curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8888');

Python:

proxy = {
    'http': '127.0.0.1:8888',
    'https': '127.0.0.1:8888',
}

r = requests.post(url, params=ticket, data=binary_data, 
                    headers=headers, proxies=proxy)

【讨论】:

  • 谢谢。它有很大帮助。在示例中,binary_data = b'hello world'。但就我而言,binary_data = "����5UU��ǚ����������h�V�������������������... .....������������������������������”(太长了,评论区都放不下) .当我运行代码时,它显示“SyntaxError: Non-ASCII character '\xef' in the file on line X (binary string line), but no encoding declaration; see python.org/dev/peps/pep-0263 for details”。我应该如何将这个“二进制数据”发送到服务器?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多