Post multipart/data with Postman to Cakephp

2019-08-12 05:56发布

问题:

I'm currently building a RESTful API in Cakephp 3. I'm trying to upload a file (with some additional data) through form-data in the Postman chrome extension. However, I'm not really sure how I can obtain the data that is received through the request.

Postman form-data

This is the data that I try to send to the pictures controller in the api folder with the following code:

  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 throws a database error which says that I'm violating a foreign key constraint (I think this is because $this->request->data is empty). However, I only want to see how the posted data is looking but the $this->request->data doesn't show up when I try to output it with the debug() function. I tried to post a JSON body which actually does work. My question is how to get the data in the controller that is send through form-data.

edit I did managed to output the request data which is indeed empty but $this->request-is('post') is true. When I try to output $this->request with debug() I get the following information:

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

Does anyone know what I'm doing wrong here? It seems like I'm receiving the text values but not the file that is also send. Besides that, I have still no idea how to obtain the data like the album_id and description.

edit 2 When I output $this->request->input() (without json_decode) with debug() I get the following output:

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

My question is now how do I obtain the file that also send through the same request? (the last boundary seems empty)

回答1:

The reason why cake isn't setting the $this->request->data is because of the POST-request body being encoded in a JSON format.

According to the CakePHP documentation:

Applications employing REST often exchange data in non-URL-encoded post bodies. You can read input data in any format using Network\Request::input(). By providing a decoding function, you can receive the content in a deserialized format:

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

$data should now contain the information submitted by Postman.



回答2:

I finally found the solution which is by calling debug($this->request->input()) (without json_decode). The problem was that Postman freezes when the file is very large (first I tried to upload a pdf document). Postman is not suited to output entire files. I had the following headers and body:

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

This gave the following output when i try to call 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--
  '