Follow-up to #2301237: Allow creating nodes with multi-value fields.

Requesting a node that has multiple values in a field works. Creating a node with multi value field (that is not a reference) field doesn't work.

If this already works, then it's not documented how to send the values.

CommentFileSizeAuthor
#7 restws-image-support-2320083-7.patch3.03 KBbtopro

Comments

lokapujya’s picture

nicxvan’s picture

I think I'm almost there, I did have one success, but I didn't catch it in time: I've changed the image function in: https://www.drupal.org/node/1819594 to the following ( I will create a patch when I get it closer )

With this

function restws_image_support(&$payload, $resource_name) {
  /**
      * Add image field support (base64)
      * @author BLE
      * @version 1.2
      */
          // intercept payload and convert for manipulation
          $payload_array = json_decode($payload);
          // get field information for specified entity and type (bundle)
          $fields_info = field_info_instances($resource_name, $payload_array->type);
          // loop through each field looking for image type
          foreach ($fields_info as $field_name => $value) {
            $field_info = field_info_field($field_name);
            $type = $field_info['type'];
            if ($type == "image") {
              // get base64 image string
              $image_file = (isset($payload_array->$field_name)) ? $payload_array->$field_name : null;
              // remove base64 prefix metadata, if exists
			  
			  $fid_array = array();
			  
			  foreach ($image_file as &$base64_data) {
			  		  watchdog('bas64', $base64_data) // Correctly shows base64 data for each image in the array


              $result = preg_split('/^data\:image\/(.*)\;base64\,/', $base64_data, -1, PREG_SPLIT_NO_EMPTY);
				if (count($result) > 0) {
					// replace any spaces with base64-compliant '+' signs and convert to binary image
					$data = base64_decode(str_replace(' ', '+', $result[0]));
					// base64 string may not have included a metadata prefix so create instance to determine mime type
					$finfo = finfo_open();
					$mime_type = finfo_buffer($finfo, $data, FILEINFO_MIME_TYPE);
					finfo_close($finfo);
					// get and validate image extension from mime type
					$ext = str_replace('image/', '', $mime_type);
					if ($ext == "png" || $ext == "gif" || $ext == "jpeg") {
						// create filename (format: entity_name_timestamp.ext, e.g. favorite_color_survey_1363723712.png)
						$filename = $payload_array->{"type"} . "_" . time() . "." . $ext;
						// save binary image in Drupal site's public file directory
						if ($file = file_save_data($data, "public://" . $filename)) {
							file_save($file);
							// replace the base64 image string in the payload with the file id reference of the newly created image
							watchdog('INVREST', $file->fid);
							array_push($fid_array, array('fid' => $file->fid // this may be where my trouble is
							));
							watchdog('INVREST', $fid_array);
						}
					}
				}
			  }
			  
			  $payload_array->$field_name = $fid_array; // This also may be wrong
			  
            }
          }
          // convert the payload back to a json string
          $payload = json_encode($payload_array);
		  return;
}

##############@@ Array sending info:

'field_image' => array(
	  'data:image/jpeg;base64,'.encode_file('../sites/default/files/pengoothumb.jpg'),
	  'data:image/jpeg;base64,'.encode_file('../sites/default/files/tulipthumb.jpg')
	  )

I think the sending array is correct. I believe the problem is with the array push and when I output the array for the images.

nicxvan’s picture

With the above settings I get the following errors: I am pretty sure it's because I have the watchdog statements malformed, or because I am out putting the array.

Notice: Array to string conversion in DatabaseStatementBase->execute() (line 2171 of webroot/includes/database/database.inc).
Warning: strtr() expects parameter 1 to be string, array given in devel_watchdog() (line 548 of webroot/sites/all/modules/contrib/devel/devel.module).
Notice: Array to string conversion in DatabaseStatementBase->execute() (line 2171 of webroot/includes/database/database.inc).
Notice: Array to string conversion in DatabaseStatementBase->execute() (line 2171 of webroot/includes/database/database.inc).
PDOException: SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 1: INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2_0, :db_insert_placeholder_2_1, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array ( [:db_insert_placeholder_0] => 23 [:db_insert_placeholder_1] => INVREST [:db_insert_placeholder_3] => a:0:{} [:db_insert_placeholder_4] => 5 [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => http://nlinventory.com/node/91 [:db_insert_placeholder_7] => [:db_insert_placeholder_8] => 70.32.92.80 [:db_insert_placeholder_9] => 1407876276 [:db_insert_placeholder_2_0] => Array ( [fid] => 176 ) [:db_insert_placeholder_2_1] => Array ( [fid] => 177 ) ) in dblog_watchdog() (line 160 of webroot/modules/dblog/dblog.module).
nicxvan’s picture

Woohoo! Actually removing the watchdog statement that output the array fixed it, it's now working! Now just have to create tests and roll the patch.

nicxvan’s picture

Working function:

function restws_image_support(&$payload, $resource_name) { // Author @stephencrossri and @nicxvan
  /**
      * Add image field support (base64)
      * @author BLE
      * @version 1.2
      */
          // intercept payload and convert for manipulation
          $payload_array = json_decode($payload);
          // get field information for specified entity and type (bundle)
          $fields_info = field_info_instances($resource_name, $payload_array->type);
          // loop through each field looking for image type
          foreach ($fields_info as $field_name => $value) {
            $field_info = field_info_field($field_name);
            $type = $field_info['type'];
            if ($type == "image") {
              // get base64 image string
              $image_file = (isset($payload_array->$field_name)) ? $payload_array->$field_name : null;
              // remove base64 prefix metadata, if exists
			  
			  $fid_array = array();
			  
			  foreach ($image_file as &$base64_data) {
			  		  
              $result = preg_split('/^data\:image\/(.*)\;base64\,/', $base64_data, -1, PREG_SPLIT_NO_EMPTY);
				if (count($result) > 0) {
					// replace any spaces with base64-compliant '+' signs and convert to binary image
					$data = base64_decode(str_replace(' ', '+', $result[0]));
					// base64 string may not have included a metadata prefix so create instance to determine mime type
					$finfo = finfo_open();
					$mime_type = finfo_buffer($finfo, $data, FILEINFO_MIME_TYPE);
					finfo_close($finfo);
					// get and validate image extension from mime type
					$ext = str_replace('image/', '', $mime_type);
					if ($ext == "png" || $ext == "gif" || $ext == "jpeg") {
						// create filename (format: entity_name_timestamp.ext, e.g. favorite_color_survey_1363723712.png)
						$filename = $payload_array->{"type"} . "_" . time() . "." . $ext;
						// save binary image in Drupal site's public file directory
						if ($file = file_save_data($data, "public://" . $filename)) {
							file_save($file);
							// replace the base64 image string in the payload with the file id reference of the newly created image
							array_push($fid_array, array('fid' => $file->fid
							));
						}
					}
				}
			  }
			  
			  $payload_array->$field_name = $fid_array;
			  
            }
          }
          // convert the payload back to a json string
          $payload = json_encode($payload_array);
		  return;
}
nicxvan’s picture

I am going to redo the patch on issue: https://www.drupal.org/node/1819594 since it shouldn't break even if your patch isn't included. I'll try to write the tests too.

btopro’s picture

StatusFileSize
new3.03 KB

not perfect but serviceable. made as a real patch for those using this til #1819594: PUT/update fails with 406 on entity/node that contains an image/file is resolved

lokapujya’s picture

Assigned: lokapujya » Unassigned
nicxvan’s picture

Status: Active » Needs review

Test it.

Status: Needs review » Needs work

The last submitted patch, 7: restws-image-support-2320083-7.patch, failed testing.

mariano.barcia’s picture

I've started testing the patch contributed here, and ended up building a module.

Please see #2452759: [D7] RESTful web services support for files and images.

Reviewing and testing welcome, thank you in advance.

mariano.barcia’s picture

Status: Needs work » Closed (won't fix)

Closing this issue, as there is now a new module for this.
https://www.drupal.org/project/restws_file
Please refer to it, thank you.