使用 Postman 将 multipart/data 发布到 Cakephp

Posted

技术标签:

【中文标题】使用 Postman 将 multipart/data 发布到 Cakephp【英文标题】:Post multipart/data with Postman to Cakephp 【发布时间】:2016-06-17 06:43:19 【问题描述】:

我目前正在 Cakephp 3 中构建一个 RESTful API。我正在尝试通过 Postman chrome 扩展中的表单数据上传一个文件(带有一些附加数据)。但是,我不确定如何获取通过请求接收到的数据。

Postman form-data

这是我尝试使用以下代码发送到 api 文件夹中的图片控制器的数据:

  public function add()
    debug($this->request->data);
    $picture = $this->Pictures->newEntity($this->request->data);
    if ($this->Pictures->save($picture)) 
        $message = 'Saved';
     else 
        $message = 'Error';
    
    $this->set([
        'message' => $message,
        'picture' => $picture,
        '_serialize' => ['message', 'picture']
    ]);
   

这会引发一个数据库错误,表明我违反了外键约束(我认为这是因为 $this->request->data 为空)。但是,我只想查看发布的数据的外观,但是当我尝试使用 debug() 函数输出它时,$this->request->data 没有出现。我试图发布一个确实有效的 JSON 正文。我的问题是如何获取通过表单数据发送的控制器中的数据。

编辑 我确实设法输出了确实为空的请求数据,但$this->request-is('post') 是真的。当我尝试使用debug() 输出$this->request 时,我得到以下信息:

object(Cake\Network\Request) 
params => [
    'plugin' => null,
    'controller' => 'Pictures',
    'action' => 'add',
    '_ext' => null,
    'pass' => [],
    'prefix' => 'api',
    'isAjax' => false
]
data => null
query => []
cookies => []
url => 'api/pictures/add'
base => ''
webroot => '/'
here => '/api/pictures/add'
trustProxy => false
[protected] _environment => [
    'USER' => 'www-data',
    'HOME' => '/var/www',
    'FCGI_ROLE' => 'RESPONDER',
    'QUERY_STRING' => '',
    'REQUEST_METHOD' => 'POST',
    'CONTENT_TYPE' => 'multipart/form-data',
    'CONTENT_LENGTH' => '375',
    'SCRIPT_NAME' => '/index.php',
    'REQUEST_URI' => '/api/pictures/add',
    'DOCUMENT_URI' => '/index.php',
    'DOCUMENT_ROOT' => '/home/vagrant/Apps/vecto.app/webroot',
    'SERVER_PROTOCOL' => 'HTTP/1.1',
    'GATEWAY_INTERFACE' => 'CGI/1.1',
    'SERVER_SOFTWARE' => 'nginx/1.7.9',
    'REMOTE_ADDR' => '10.33.10.1',
    'REMOTE_PORT' => '55842',
    'SERVER_ADDR' => '10.33.10.10',
    'SERVER_PORT' => '80',
    'SERVER_NAME' => 'vecto.app',
    'REDIRECT_STATUS' => '200',
    'SCRIPT_FILENAME' => '/home/vagrant/Apps/vecto.app/webroot/index.php',
    'HTTP_HOST' => 'vecto.app',
    'HTTP_CONNECTION' => 'keep-alive',
    'HTTP_CONTENT_LENGTH' => '375',
    'HTTP_ACCEPT' => 'multipart/form-data',
    'HTTP_POSTMAN_TOKEN' => 'be1a629c-d81e-b19b-4e0f-294a46779150',
    'HTTP_CACHE_CONTROL' => 'no-cache',
    'HTTP_ORIGIN' => 'chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop',
    'HTTP_AUTHORIZATION' => 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjksImV4cCI6MTQ1NzYyOTU3NH0.NnjXWEQCno3PUiwHhnUCBjiknR-NlmT42oPLA5KhuYo',
    'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
    'HTTP_CONTENT_TYPE' => 'multipart/form-data',
    'HTTP_DNT' => '1',
    'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',
    'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8,nl;q=0.6',
    'PHP_SELF' => '/index.php',
    'REQUEST_TIME_FLOAT' => (float) 1457090949.1208,
    'REQUEST_TIME' => (int) 1457090949,
    'HTTP_X_HTTP_METHOD_OVERRIDE' => null,
    'ORIGINAL_REQUEST_METHOD' => 'POST',
    'HTTPS' => false,
    'HTTP_X_REQUESTED_WITH' => null
]
[protected] _detectors => [
    'get' => [
        'env' => 'REQUEST_METHOD',
        'value' => 'GET'
    ],
    'post' => [
        'env' => 'REQUEST_METHOD',
        'value' => 'POST'
    ],
    'put' => [
        'env' => 'REQUEST_METHOD',
        'value' => 'PUT'
    ],
    'patch' => [
        'env' => 'REQUEST_METHOD',
        'value' => 'PATCH'
    ],
    'delete' => [
        'env' => 'REQUEST_METHOD',
        'value' => 'DELETE'
    ],
    'head' => [
        'env' => 'REQUEST_METHOD',
        'value' => 'HEAD'
    ],
    'options' => [
        'env' => 'REQUEST_METHOD',
        'value' => 'OPTIONS'
    ],
    'ssl' => [
        'env' => 'HTTPS',
        'options' => [
            (int) 0 => (int) 1,
            (int) 1 => 'on'
        ]
    ],
    'ajax' => [
        'env' => 'HTTP_X_REQUESTED_WITH',
        'value' => 'XMLHttpRequest'
    ],
    'flash' => [
        'env' => 'HTTP_USER_AGENT',
        'pattern' => '/^(Shockwave|Adobe) Flash/'
    ],
    'requested' => [
        'param' => 'requested',
        'value' => (int) 1
    ],
    'json' => object(Closure) 

    ,
    'xml' => object(Closure) 

    ,
    'mobile' => object(Closure) 

    ,
    'tablet' => object(Closure) 

    ,
    'api' => object(Closure) 

    
]
[protected] _detectorCache => [
    'json' => false,
    'xml' => false,
    'api' => false,
    'post' => true,
    'ajax' => false
]
[protected] _input => '------WebKitFormBoundaryRDGaZEhAuN4lILOR
Content-Disposition: form-data; name="album_id"

 2
  ------WebKitFormBoundaryRDGaZEhAuN4lILOR
  Content-Disposition: form-data; name="description"

  haiahaahahahdaisdhisadhisadihsdhiiahsd
  ------WebKitFormBoundaryRDGaZEhAuN4lILOR
  Content-Disposition: form-data; name="favorite"

  true
  ------WebKitFormBoundaryRDGaZEhAuN4lILOR--
  '
   [protected] _session => object(Cake\Network\Session) 
      [protected] _engine => null
      [protected] _started => null
      [protected] _lifetime => '1440'
      [protected] _isCLI => false
   
 

有谁知道我在这里做错了什么?似乎我正在接收文本值,但不是也发送的文件。除此之外,我仍然不知道如何获取album_id和description等数据。

编辑 2 当我使用 debug() 输出 $this->request->input() (没有 json_decode)时,我得到以下输出:

'------WebKitFormBoundarykeFhH2KM4LdYgsH0
Content-Disposition: form-data; name="album_id"

2
------WebKitFormBoundarykeFhH2KM4LdYgsH0
Content-Disposition: form-data; name="description"

haiahaahahahdaisdhisadhisadihsdhiiahsd
------WebKitFormBoundarykeFhH2KM4LdYgsH0
Content-Disposition: form-data; name="favorite"

true
------WebKitFormBoundarykeFhH2KM4LdYgsH0--
'

我现在的问题是如何获取也通过相同请求发送的文件? (最后一个边界似乎是空的)

【问题讨论】:

据我了解...您想要保存它吗?如果您不想保存,则不必调用save() 函数。 我想保存它,但有一些额外的逻辑,即创建了一个到 AWS S3 的链接。现在,我只想输出通过 Postman 中的表单数据发送的数据,但我不确定它是否被接收或数据存储在什么变量中。 能和这个类似吗?我对邮递员一点也不熟悉:***.com/a/31977373/1604068(顺便说一句:你好达奇;)) 哈哈 ;)。我已经找到了那个帖子,但问题是使用 application/x-www-form-urlencoded 你不能发送任何文件。到目前为止,我没有找到任何解决方案。我已经尝试使用 multipart/form-data 手动设置接受和内容类型。这也不起作用,但我得到了一些额外的信息(见编辑) ***.com/a/39037889/1979380 【参考方案1】:

cake 没有设置 $this->request->data 的原因是 POST 请求正文以 JSON 格式编码。

According to the CakePHP documentation:

使用REST 的应用程序经常在非 URL 编码的帖子正文中交换数据。您可以使用 Network\Request::input() 读取任何格式的输入数据。通过提供解码功能,可以接收反序列化格式的内容:

// Get JSON encoded data submitted to a PUT/POST action
$data = $this->request->input('json_decode');

$data 现在应该包含 Postman 提交的信息。

【讨论】:

如果不反序列化格式,它将返回除我也发送的文件之外的信息(边界似乎为空)。这个输入是否也包含文件? 我没有测试过上传文件,也没有在食谱中找到任何与发送文件的请求相关的内容,我建议你尝试一下,因为我现在无法测试:/对不起。 没问题 ;)。如果我有一个,我会发布解决方案。现在看来,当我尝试上传内容类型设置为 multipart/form-data 的文件时,Postman 冻结了(如果我让 content-type 出来,cakephp 没有接收到正文)。也许最好用 cURL 或类似的东西来执行测试。【参考方案2】:

我终于找到了解决方案,即调用 debug($this->request->input()) (不带 json_decode)。问题是当文件非常大时 Postman 会冻结(首先我尝试上传 pdf 文档)。 Postman 不适合输出整个文件。我有以下标题和正文:

 public function add()
     debug($this->request->input());
 

当我尝试调用 debug($this->request->input()) 时,这给出了以下输出:

'------WebKitFormBoundaryjQIb9c3vvKj8TzQ3
 Content-Disposition: form-data; name="album_id"

 2
 ------WebKitFormBoundaryjQIb9c3vvKj8TzQ3
 Content-Disposition: form-data; name="description"

  haiahaahahahdaisdhisadhisadihsdhiiahsd
  ------WebKitFormBoundaryjQIb9c3vvKj8TzQ3
  Content-Disposition: form-data; name="favorite"

  true
  ------WebKitFormBoundaryjQIb9c3vvKj8TzQ3
  Content-Disposition: form-data; name="uploadfile";          filename="test.txt"
  Content-Type: text/plain

  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do   eiusmod
  tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim   veniam,
  quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
  consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
  cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat   cupidatat non
  proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  ------WebKitFormBoundaryjQIb9c3vvKj8TzQ3--
  '

【讨论】:

以上是关于使用 Postman 将 multipart/data 发布到 Cakephp的主要内容,如果未能解决你的问题,请参考以下文章

带文件的表单提交

文件上传和下载

如何上传文件数组?

如何使用 Postman 将图像发送到烧瓶服务器

如何使用 Postman 将 XML 数据发布到 Web 服务?

如何使用 POSTMAN 应用程序将文件上传到 Amazon S3