Updating a binary field of contentlet

33 views
Skip to first unread message

mube...@gmail.com

unread,
Sep 2, 2017, 3:42:46 PM9/2/17
to dotCMS User Group

Hello,


I have a content type: User Profile. It has a binary field I am using to store an image. I am updating the contentlets using AJAX PUT from the client side. (My server java / plugin skills are not good/inexistent at this point).

If the user wants to remove the existing image from the front end, I would like to be able to remove the image from the contentlet (or alternatively replace it with a generic small image (like a user avatar) or just replace it with nothing).


I tried the following but was not successful (Note: I did not get a JavaScript error, nor a dotCMS server error on log):

Am I doing something wrong? Can someone please suggest a way to accomplish what I am trying to do?


Below are my attempts.

Thank you!

Mube


Attempt 1: I tried to overwrite the image with null by appending the 'file' key with a value of null (I have to admit this was a guess…)

dataform.append(‘file', null);


Attempt 2: I tried to upload an image from the server that will replace the existing image:


2.1


var xhr = new XMLHttpRequest();

                xhr.onreadystatechange = function(){

                    if (this.readyState == 4 && this.status == 200){

                        console.log(this.response, typeof this.response);

                        dataform.append('file', this.response);

                    }

                }

                xhr.open('GET', 'http://[server IP address]/application/themes/orizonto/images/layout/smiley2.png',true);

                xhr.responseType = 'blob';

                xhr.send();


2.2                

            fetch('http://[server IP address]/application/themes/orizonto/images/layout/smiley2.png’)

              .then(res => res.blob()) // Gets the response and returns it as a blob

              .then(blob => {

               dataform.append(‘file', blob);

            });



The AJAX code:

$.ajax({

                url: '/api/content/publish/1',

                type: 'PUT',

                cache:false,

                data: dataform,

                processData: false,

                contentType: false,


                success: function(data, status, xhr) {

                    $('#profileImageHeader').attr("src", $('#profileImage').attr('src'));

                    

                    bootstrap_alert.success('Profile updated successfully');

                    

                    console.log("works!");

                    var a = xhr.getAllResponseHeaders();

                    var id = a.substring(a.indexOf('identifier: ') + 'identifier: '.length , a.indexOf('\n', a.indexOf('identifier: ') + 'identifier: '.length));

                    

                    },

                error: function(data,status,xhr) {

                

                bootstrap_alert.clear();

                

                enableRequestBtn();

                console.log(data);

                bootstrap_alert.danger('Your profile could not be updated. Please check your entries and try again');

                },

            });

Mark Pitely

unread,
Sep 5, 2017, 10:11:10 AM9/5/17
to dot...@googlegroups.com
Mube,

Looks to me that you are appending the file at the wrong place. You need to append the file to the XHR request that has the structure name, identifier of the contentlet, etc.
Here's some code that does this correctly:

function addcomment(){   
   
    var formData = new FormData();
 request = new XMLHttpRequest();

//WHILE THIS IS First, this only executes when the XHR/Ajax call is complete!
//Adding the file here would be pointless, we are already done talking to the server
request.onreadystatechange = function() {
  if (request.readyState == 4){
        if (request.status === 200) {
          console.log("Create Eiffel Connect:");   
          console.log(request.responseText);
            location.href="${VTLSERVLET_URI}?dotcache=refresh";         //reload the page
        } else { 
           console.log("Error", request.statusText); 
        } 
}
};

request.open("POST", "/api/content/publish/1", true);  
//grab all our data from our form
var comment=document.getElementById('Comment').value;
var d=new Date();
var mon=d.getMonth()+1;
var day=d.getDate();
var atime=d.getFullYear()+"-"+mon+"-"+day+" "+d.getHours()+":"+d.getMinutes()+":"+d.getSeconds();
console.log(atime);


//Create our datablob which we will send to the API. It has to have either STname  (for a new entry)
//OR the identifier of the existing object we are updating!
//This creates a new entry.
 var dataObj={
          'stName':'ParisContentComment',
          'identifier1' : document.identifier,
          'pageurl' : '$VTLSERVLET_URI',
          'user' : '$reviewuser',
          'useremail' : '$reviewemail',
          'userdepartment' : '$reviewdept',
          'userjob' : '$reviewjob',
          'highlight' : document.highlit,
          'comment' : comment,
          'reported': atime,
          'contentHost':'SYSTEM_HOST'};   
   
 formData.append('json',JSON.stringify(dataObj));   
 

//we cannot pass the image the same way as a text field.
//GET The image.

var theimager=document.getElementById('tpic');
var file=theimager.files[0];
//here we are just using the HTML input type equals file. You can get your image other ways!

if (file)
formData.append("document", file);
//append the file to our existing dataObj. 
//obviously only if you have a file that has been attached.
  
 request.send(formData);  
  
   
       

}



Mark Pitely
Marywood University

--
http://dotcms.com - Open Source Java Content Management
---
You received this message because you are subscribed to the Google Groups "dotCMS User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dotcms+unsubscribe@googlegroups.com.
To post to this group, send email to dot...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dotcms/e6015a01-c3f9-492b-85fa-2024012eae3d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

mube...@gmail.com

unread,
Sep 5, 2017, 3:01:15 PM9/5/17
to dotCMS User Group
Thanks for your feedback, Mark.

I am using the XHR piece of code only to get an image (user avatar) from my server. Then I am attempting to use AJAX to load the user avatar onto the contentlet.
Here's how I am appending the structure name and identifier of the contentlet.

var dataObj={
   'stName':'UserProfile'
};
dataObj.identifier = $('#conIdentifier').val();

... I append a few more fields of the contentlet then I do the following ...

dataform.append('json',JSON.stringify(dataObj))

Note: the code below works fine. I am using it to update the contenlet (including loading a file the user selects from their machine using the input element. What I am struggling with is loading a file from the server or just getting rid of the existing image. 

var imageFile = document.getElementById('photo').files[0];

if (imageFile != undefined) {
   blob = canvasToBlob(loadedCanvas, imageFile.type);
   dataform.append('file', blob);
}

Then comes the AJAX code I provided above.
So I am still not sure what I am doing wrong.

Mube
To unsubscribe from this group and stop receiving emails from it, send an email to dotcms+un...@googlegroups.com.

Mark Pitely

unread,
Sep 5, 2017, 3:38:53 PM9/5/17
to dot...@googlegroups.com
Okay, sounds like you understand the main part of it.
You are not getting any errors from the server - or any feedback at all from the return?

Oh, here's a way to delete (from a previous dotCMS entry):
It isn't obvious, but if you want to make a call to *remove* a Binary File from a contentlet, you need to do a little trickery, namely finding a null file object that the API will accept.
Here's the code:

request.open("POST", "/api/content/publish/1", true);  
  var dataObj={ 'identifier': tkey,
          'stName':'webPageContent',

          'contentHost':'SYSTEM_HOST'};   
formData.append('json',JSON.stringify(dataObj)); 

// just doing 'image':null above does not work.


//Correct empty file object
//may not work on IE, Chrome <37 as they didn't have a file object but blob.
//'image' is the field name
var f = new File([""], null);
 formData.append("image", f); 

 request.send(formData);
}

Hope this saves someone some Trial (and Tribulation) and Error.





M

To unsubscribe from this group and stop receiving emails from it, send an email to dotcms+unsubscribe@googlegroups.com.

To post to this group, send email to dot...@googlegroups.com.

mube...@gmail.com

unread,
Sep 6, 2017, 2:57:26 PM9/6/17
to dotCMS User Group
Mark,
I tried your latest suggestion (i.e: var f = new File([""], null);). The contentlet update failed with the following error:

[06/09/17 18:45:02:361 UTC] ERROR rest.ContentResource: Error saving Contentletcom.dotmarketing.portlets.contentlet.business.DotContentletValidationException: Error occurred while processing the file:Source file is 0 length, failing /opt/dotcms_3.6.0/dotserver/tomcat-8.0.18/webapps/ROOT/assets/tmp_upload/dotcms.org.2931/1504723502291/null

Then I tried this:
var f = new File(["i"], null);
As a result, the contentlet seemed succesfully updated (including the binary field). But then I get this error:

[06/09/17 18:47:22:478 UTC] ERROR servlets.BinaryExporterServlet: java.io.IOException: Broken pipe

Any idea on the meaning of the second error or why I am getting it, ..or any other suggestion?

Thanks
Mube

Mark Pitely

unread,
Sep 7, 2017, 9:55:40 AM9/7/17
to dot...@googlegroups.com
Hrm. That really works for me. You are using Chrome>37 and not IE? There's some sort of issue with older browsers and how they treat the file object.
It's an undocumented trick, anyway. Perhaps your version is too old? (looks like 3.6)

You are real close, I think, to being able to do what you need. I'm not sure why it isn't working for you.

M


To unsubscribe from this group and stop receiving emails from it, send an email to dotcms+unsubscribe@googlegroups.com.

To post to this group, send email to dot...@googlegroups.com.

mube...@gmail.com

unread,
Sep 7, 2017, 12:22:56 PM9/7/17
to dotCMS User Group
I am using Chrome versions > 37, not IE.
I am using dotCMS Community Edition 3.6.0. I wanted to wait a bit before upgrading. Maybe this is a sign it's time to upgrade... Which version of dotCMS are you using?
Yeah, it looks like I am close. I am just worried about that error I am getting on dotCMS.

I am hoping I will be able to have this resolved, somehow. Hopefully I can get some more help.

Thanks Mark
Mube
Reply all
Reply to author
Forward
0 new messages