Hi,
I am trying to make a php script to add thousands of pictures to existing contacts bpm.
Support helped me already and told that I should create (POST) a new entry in SysImageCollection with json {id: guid, name: guid}.
Then upload the image binary (base64, zipped or not, I tried them all) as an update (PUT) to SysImageCollection(guid'guid')/PreviewData.
Everything runs correct but I don't see any picture change in the contacts.
I use the guid of the contact in both steps.
Maybe I have to use a fresh guid and link that guid to the ContactCollection afterwards?
Does anyone have an idea what the json is to update the the profile picture for a contact?
Thanks in advance,
Kristof Leroux - Laranea
Like
It's hard to say how to create the integration on PHP. I created the functionality on c# and caught the requests with fiddler.
using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Net; using System.Xml; using System.Xml.Linq; namespace TransferImageViaOData { class Program { // String of address bpm’online OData servise. private const string serverUri = "https://023148-crm-bundle.bpmonline.com/0/ServiceModel/EntityDataService.svc/"; private const string authServiceUtri = "https://023148-crm-bundle.bpmonline.com/ServiceModel/AuthService.svc/Login"; // Links to XML name spaces. private static readonly XNamespace ds = "http://schemas.microsoft.com/ado/2007/08/dataservices"; private static readonly XNamespace dsmd = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"; private static readonly XNamespace atom = "http://www.w3.org/2005/Atom"; private static readonly Guid ContactId = new Guid("410006e1-ca4e-4502-a9ec-e54d922d2c00"); static void Main(string[] args) { var file = ReadFile("z:/2SupportLine/features.png"); var id = CreateBpmEntityByOdataHttpExample(); TransferImage(id, "Data", file); UpdateContactAvatar(id); } public static Guid CreateBpmEntityByOdataHttpExample() { Guid id = Guid.NewGuid(); // Creating a xml message containing data on the created object. var content = new XElement(dsmd + "properties", new XElement(ds + "Id", id.ToString()), new XElement(ds + "HasRef", 0), new XElement(ds + "MimeType", "image/png"), new XElement(ds + "Name", "test1.png") ); var entry = new XElement(atom + "entry", new XElement(atom + "content", new XAttribute("type", "application/xml"), content)); Console.WriteLine(entry.ToString()); // Creating a request to the service which will add a new object to the contacts collection. var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection/"); request.Credentials = new NetworkCredential("Supervisor", "Supervisor"); request.Method = "POST"; request.Accept = "application/atom+xml"; request.ContentType = "application/atom+xml;type=entry"; // Recording the xml message to the request stream. using (var writer = XmlWriter.Create(request.GetRequestStream())) { entry.WriteTo(writer); } // Receiving a response from the service regarding the operation implementation result. using (WebResponse response = request.GetResponse()) { if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created) { // Processing the operation implementation result. } } return id; } public static void TransferImage(Guid fileRecordId, string columnName, byte[] file) { // Creating a request to the service which will add a new object to the contacts collection. var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection(guid'" + fileRecordId.ToString() + "')/" + columnName); request.Credentials = new NetworkCredential("Supervisor", "Supervisor"); request.Method = "PUT"; request.Accept = "application/octet-stream,application/json;odata=verbose"; request.ContentType = "multipart/form-data;boundary=+++++"; // Recording the xml message to the request stream. using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(file, 0, file.Length); } // Receiving a response from the service regarding the operation implementation result. using (WebResponse response = request.GetResponse()) { if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created) { // Processing the operation implementation result. } } } public static void UpdateContactAvatar(Guid fileRecordId) { var content = new XElement(dsmd + "properties", new XElement(ds + "PhotoId", fileRecordId) ); var entry = new XElement(atom + "entry", new XElement(atom + "content", new XAttribute("type", "application/xml"), content) ); var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "ContactCollection(guid'" + ContactId + "')"); request.Credentials = new NetworkCredential("Supervisor", "Supervisor"); // or request.Method = "MERGE"; request.Method = "PUT"; request.Accept = "application/atom+xml"; request.ContentType = "application/atom+xml;type=entry"; // Recording the xml message to the request stream. using (var writer = XmlWriter.Create(request.GetRequestStream())) { entry.WriteTo(writer); } // Receiving a response from the service regarding the operation implementation result. using (WebResponse response = request.GetResponse()) { // Processing the operation implementation result. } } public static byte[] ReadFile(string filePath) { byte[] imageArray = System.IO.File.ReadAllBytes(filePath); return imageArray; } } }
Please use the code below:
<?php
/*Please change this to you product name*/
define("baseUri", "https://023665-crm-bundle.bpmonline.com");
define("serverUri", baseUri . "/0/ServiceModel/EntityDataService.svc");
/*Please change this to you account setting*/
define("user", "Dmitro");
define("password", "123456789");
/*Please change this user_id to new user_id value for the user whose avatar needs to be changed*/
$user_id = 'c4ed336c-3e9b-40fe-8b82-5632476472b4';
/*Please change this file name*/
$file_name = 'test_img.png';
$file_id = CreateBpmEntityFile($file_name);
TransferImage($file_id, $file_name);
UpdateContactAvatar($user_id, $file_id);
function CreateBpmEntityFile($file_name) {
$headers = [
'Accept: application/atom+xml',
'Content-Type: application/atom+xml;type=entry',
"Authorization: Basic " . base64_encode(user . ':' . password),
'Expect: 100-continue',
];
$uid = GetUid();
$postData = <<<XML
<?xml version="1.0" encoding="utf-8"?><entry xmlns="http://www.w3.org/2005/Atom"><content type="application/xml"><properties xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><Id xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">$uid</Id><HasRef xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">0</HasRef><MimeType xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">image/png</MimeType><Name xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">$file_name</Name></properties></content></entry>
XML;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, serverUri . "/SysImageCollection/");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_exec($ch);
curl_close($ch);
return $uid;
}
function TransferImage($id, $file_name) {
$fh_res = fopen($file_name, 'r');
$xml_data = fread($fh_res, filesize($file_name));
$headers = [
"Accept: application/octet-stream,application/json;odata=verbose",
"Content-type: multipart/form-data;boundary=+++++",
"Authorization: Basic " . base64_encode(user . ':' . password),
"Expect: 100-continue",
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, serverUri . "/SysImageCollection(guid'$id')/Data");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_exec($ch);
fclose($fh_res);
}
function UpdateContactAvatar($user_id, $file_id) {
$headers = [
'Accept: application/atom+xml',
'Content-Type: application/atom+xml;type=entry',
"Authorization: Basic " . base64_encode(user . ':' . password),
];
$postData = <<<XML
<?xml version="1.0" encoding="utf-8"?><entry xmlns="http://www.w3.org/2005/Atom"><content type="application/xml"><properties xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><PhotoId xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">$file_id</PhotoId></properties></content></entry>
XML;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, serverUri . "/ContactCollection(guid'$user_id')");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_exec($ch);
curl_close($ch);
}
/**
* Generate uniq id
*
* @return string
*/
function GetUid() {
$uid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000,
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
return $uid;
}
Mark Bailey,
Thanks Mark for your solution. It is working but I need to use it as a service and my implementation goes like::
// Endpoint
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json)]
public string UploadContactPicture(Data data)
{
CifNoVar = data.CIFNo;
ContactId = Guid.Parse(GetContactIdByCIF(data.CIFNo));
var file = ReadFile(data.Image);
var id = CreateBpmEntityByOdataHttpExample();
TransferImage(id, "Data", file);
UpdateContactAvatar(id);
return ContactId.ToString();
}
where Data is::
[DataContract]
public class Data
{
[DataMember]
public string CIFNo { get; set; }
[DataMember]
public string Image { get; set; }
}
The UploadContactPicture is working well to upload a contact picture when my implementation is::
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json)]
public string UploadContactPicture(string CIFNo)
{
CifNoVar = CIFNo;
ContactId = Guid.Parse(GetContactIdByCIF(CIFNo));
var file = ReadFile("E:/SBL_QA/Terrasoft.WebApp/conf/content/img/OBSWConsultationPanelSchema-DefaultContactPhoto.jpg");
var id = CreateBpmEntityByOdataHttpExample();
TransferImage(id, "Data", file);
UpdateContactAvatar(id);
return ContactId.ToString();
}
How can I use a JSON object(Model object) as a parameter to the UploadContactPicture method to successfully upload a picture as shown in the example above.
Dear,
In order to resolve the issue please use the article by the link below:
Best regards,
Norton
Norton Lingard,
Hi Norton, thanks for your reply. I had tried it, but it didn't work. It says::
403 - Forbidden: Access is denied. You do not have permission to view this directory or page using the credentials that you supplied.
This is my full implementation::
namespace Terrasoft.Configuration.SBLCustomNamespace
{
using System;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using Terrasoft.Core;
using Terrasoft.Web.Common;
using Terrasoft.Core.Entities;
using Terrasoft.Core.DB;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq;
using System.Web.Hosting;
using System.Runtime.Serialization;
[DataContract]
public class Data
{
[DataMember]
public string CIFNo { get; set; }
[DataMember]
public string Image { get; set; }
}
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class SBLContactPictureUploaderService: BaseService
{
// Link to the UserConnection instance required to access the database.
private SystemUserConnection _systemUserConnection;
private SystemUserConnection SystemUserConnection {
get {
return _systemUserConnection ?? (_systemUserConnection = (SystemUserConnection)AppConnection.SystemUserConnection);
}
}
// String of address bpm’online OData service.
private const string serverUri = "https://qacrm.siddharthabank.com/0/ServiceModel/EntityDataService.svc/";
private const string authServiceUtri = "https://qacrm.siddharthabank.com/ServiceModel/AuthService.svc/Login";
// Links to XML name spaces.
private readonly XNamespace ds = "http://schemas.microsoft.com/ado/2007/08/dataservices";
private readonly XNamespace dsmd = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
private readonly XNamespace atom = "http://www.w3.org/2005/Atom";
private Guid ContactId = Guid.NewGuid();
private string CifNoVar = string.Empty;
// A method that returns the contact's ID by its name.
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json)]
public string UploadContactPicture(Data data)
{
CifNoVar = data.CIFNo;
ContactId = Guid.Parse(GetContactIdByCIF(data.CIFNo));
var file = ReadFile(data.Image);
var id = CreateBpmEntityByOdataHttpExample();
TransferImage(id, "Data", file);
UpdateContactAvatar(id);
return ContactId.ToString();
}
public Guid CreateBpmEntityByOdataHttpExample()
{
Guid id = Guid.NewGuid();
// Creating a xml message containing data on the created object.
var content = new XElement(dsmd + "properties",
new XElement(ds + "Id", id.ToString()),
new XElement(ds + "HasRef", 0),
new XElement(ds + "MimeType", "image/jpg"),
new XElement(ds + "Name", CifNoVar.ToString().Trim()+".jpg")
);
var entry = new XElement(atom + "entry",
new XElement(atom + "content",
new XAttribute("type", "application/xml"), content));
Console.WriteLine(entry.ToString());
// Creating a request to the service which will add a new object to the contacts collection.
var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection/");
request.Credentials = new NetworkCredential("Supervisor", "Supervis0r@1234%");
request.Method = "POST";
request.Accept = "application/atom+xml";
request.ContentType = "application/atom+xml;type=entry";
// Recording the xml message to the request stream.
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
// Receiving a response from the service regarding the operation implementation result.
using (WebResponse response = request.GetResponse())
{
if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created)
{
// Processing the operation implementation result.
}
}
return id;
}
public void TransferImage(Guid fileRecordId, string columnName, byte[] file)
{
// Creating a request to the service which will add a new object to the contacts collection.
var request = (HttpWebRequest)HttpWebRequest.Create(serverUri + "SysImageCollection(guid'" + fileRecordId.ToString() + "')/" + columnName);
request.Credentials = new NetworkCredential("Supervisor", "Supervis0r@1234%");
request.Method = "PUT";
request.Accept = "application/octet-stream,application/json;odata=verbose";
request.ContentType = "multipart/form-data;boundary=+++++";
// Recording the xml message to the request stream.
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(file, 0, file.Length);
}
// Receiving a response from the service regarding the operation implementation result.
using (WebResponse response = request.GetResponse())
{
if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Created)
{
// Processing the operation implementation result.
}
}
}
public void UpdateContactAvatar(Guid fileRecordId)
{
var content = new XElement(dsmd + "properties",
new XElement(ds + "PhotoId", fileRecordId)
);
var entry = new XElement(atom + "entry",
new XElement(atom + "content",
new XAttribute("type", "application/xml"),
content)
);
var request = (HttpWebRequest)HttpWebRequest.Create(serverUri
+ "ContactCollection(guid'" + ContactId + "')");
request.Credentials = new NetworkCredential("Supervisor", "Supervis0r@1234%");
// or request.Method = "MERGE";
request.Method = "PUT";
request.Accept = "application/atom+xml";
request.ContentType = "application/atom+xml;type=entry";
// Recording the xml message to the request stream.
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
// Receiving a response from the service regarding the operation implementation result.
using (WebResponse response = request.GetResponse())
{
// Processing the operation implementation result.
}
}
public static byte[] ReadFile(string filePath)
{
byte[] imageArray = System.IO.File.ReadAllBytes(filePath);
return imageArray;
}
// A method that returns the contact's ID by its name.
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json)]
public string GetContactIdByName(string Name){
// The default result.
var result = "";
// An EntitySchemaQuery instance that accesses the Contact table of the database.
var esq = new EntitySchemaQuery(SystemUserConnection.EntitySchemaManager, "Contact");
// Adding columns to the query.
var colId = esq.AddColumn("Id");
var colName = esq.AddColumn("Name");
// Filter the query data.
var esqFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Name", Name);
esq.Filters.Add(esqFilter);
// Get the result of the query.
var entities = esq.GetEntityCollection(SystemUserConnection);
// If the data is received.
if (entities.Count > 0)
{
// Return the value of the "Id" column of the first record of the query result.
result = entities[0].GetColumnValue(colId.Name).ToString();
// You can also use this option:
// result = entities [0]. GetTypedColumnValue <string> (colId.Name);
}
// Return the result.
return result;
}
public string GetContactIdByCIF(string CIFNo){
// The default result.
var result = "";
// An EntitySchemaQuery instance that accesses the Contact table of the database.
var esq = new EntitySchemaQuery(SystemUserConnection.EntitySchemaManager, "Contact");
// Adding columns to the query.
var colId = esq.AddColumn("Id");
var colName = esq.AddColumn("SBLCIF");
// Filter the query data.
var esqFilter = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "SBLCIF", CIFNo);
esq.Filters.Add(esqFilter);
// Get the result of the query.
var entities = esq.GetEntityCollection(SystemUserConnection);
// If the data is received.
if (entities.Count > 0)
{
// Return the value of the "Id" column of the first record of the query result.
result = entities[0].GetColumnValue(colId.Name).ToString();
// You can also use this option:
// result = entities [0]. GetTypedColumnValue <string> (colId.Name);
}
// Return the result.
return result;
}
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json)]
public string InsertContact(string contactName)
{
contactName = contactName ?? "Unknown contact";
var ins = new Insert(UserConnection)
.Into("Contact")
.Set("Name", Column.Const(contactName));
var affectedRows = ins.Execute();
var result = $"Inserted new contact with name '{contactName}'. {affectedRows} rows affected";
return result;
}
}
}
Dear,
In order to resolve the issue please use the article by the link below:
https://community.creatio.com/questions/403-forbidden-when-using-post-custom-service
Best regards,
Norton