Discussion
Pegasystems Inc.
JP
Last activity: 7 Jul 2023 5:16 EDT
Performance issue with inserting Base64 inline images into Rich Text Editor
Hi,
Our customer reported a performance issue when opening an assignment. As per our investigation, we came to know that there are some issues with combination of RTE (Rich Text Editor) and Base64 inline images. In this post, I will share what the issue is, and how to implement a workaround.
1. Symptoms
Place a property on a section rule and configure Rich Text Editor control. Then prepare a 3-5MB image file. Drag & drop the file into RTE and click Save button. Once saved, cancel the assignment and open it again. These operations will take very long - in my local machine 3MB image took me more than 18 seconds for saving, and 18 seconds for opening (see below demo). Also, PEGA0039 is logged in the ALERT file. Our customer includes multiple image files in a single case and they are frustrated by slow system performance, sometimes causing OOM failure.
2. Root cause
From Pega 8.3 onwards, when you insert an image into RTE, system creates a Base64 code of the image and appends the entire strings within the property. You can confirm this from clipboard (src="data:image/jpeg;base64,…).
This is the specification of the current version of Pega Platform. FYI, Base64-encoded data takes about 33% more space than the original data. This means 3MB image file becomes text of 4MB. Also, reading Blob is very costly, and that is why PEGA0039 ALERT is observed.
3. Solution (Image uploader)
You can configure Image uploader from RTE control settings. This functionality is disabled by default and you need to turn on "Image" checkbox in the toolbar options.
Image uploader icon will appear in the RTE toolbar. Now user can insert images safely.
If user inserts image using this functionality, system will create an instance of Data-Content-Image class right away and only the reference is saved in the property (src="../datacontent/Image/rteImages/…). No more gigantic strings.
- Data-Content-Image class instance
- Clipboard
This approach makes the performance much faster - I tested it using the same 3MB file and it didn't take a second for both save and reopening operation.
4. Drag-and-Drop vs Copy-and-Paste
Drag-and-Drop and Copy-and-Paste are similar but two different operations. Both can insert images into RTE but we need to be aware that system behavior may differ depending on Pega version.
- Drag-and-Drop
- Copy-and-Paste
5. Variation by version
Actually, above performance issue was never reported from Pega 7.3 / 7.4 customers. So we have done experiments on 7x / 8x versions and summarized our findings in the table below. Be noted, whether Image uploader function is enabled or not also affects the behavior of Drag-and-Drop or Copy-and-Paste operation.
Version |
Drag-and-Drop with Image uploader disabled |
Drag-and-Drop with Image uploader enabled | Copy-and-Paste with Image uploader disabled | Copy-and-Paste with Image uploader enabled | Image uploader function |
---|---|---|---|---|---|
Pega 7.1.2 | Does not work (behavior: dragged image is opened in a separate new browser tab) | Does not work (behavior: dragged image is opened in a separate new browser tab) | Works, but it creates a Base64 code of the image and saves the entire strings in the property (potentially performance issue). | Works, but it creates a Base64 code of the image and saves the entire strings in the property (potentially performance issue). | Supported. This will create an instance of Data-Content-Image class and saves only the reference (fast performance). |
Pega 7.2.2 | Same as above | Works, and it creates an instance of Data-Content-Image class and saves only the reference (fast performance). | Same as above | Works, and it creates an instance of Data-Content-Image class and saves only the reference (fast performance). | Same as above |
Pega 7.3 | Does not work (behavior: nothing happens when dragged). | Same as above | Does not work (behavior: nothing happens when dragged). | Same as above | Same as above |
Pega 7.4 | Same as above | Same as above | Same as above | Same as above | Same as above |
Pega 8.1 | Same as above | Same as above | Same as above | Same as above | Same as above |
Pega 8.2 | Same as above | Same as above | Same as above | Same as above | Same as above |
Pega 8.3 | Works, but it creates a Base64 code of the image and saves the entire strings in the property (potentially performance issue). | Works, but it creates a Base64 code of the image and saves the entire strings in the property (potentially performance issue). | Works, but it creates a Base64 code of the image and saves the entire strings in the property (potentially performance issue). | Works, but it creates a Base64 code of the image and saves the entire strings in the property (potentially performance issue). | Same as above |
Pega 8.4.1 | Same as above | Same as above | Same as above | Same as above | Same as above |
Pega 8.5.1 | Same as above | Same as above | Same as above | Same as above | Same as above |
Pega 8.6 | Same as above | Same as above | Same as above | Same as above | Same as above |
Pega 8.7 | Same as above | Same as above | Same as above | Same as above | Same as above |
Pega 8.8 | Same as above | Same as above | Same as above | Same as above | Same as above |
Based upon the experiment results above, here is how I understood:
- Image uploader function was provided from version 7.1, and its specification has never been changed. It creates an instance of Data-Content-Image class and saves only the reference in any version. This is always the safest approach.
- From 7.3 to 8.2, neither Drag-and-Drop nor Copy-and-Paste was allowed for inserting images, if Image uploader function is disabled. If it is enabled, both operations worked and Data-Content-Image approach was applied (not Base64 approach). So, no performance issue was reported in these versions.
- From 8.3 onwards including the latest 8.8, regardless of Image uploader settings, both Drag-and-Drop and Copy-and-Paste are allowed for inserting images. This is supposed to be an enhancement for user experience but in exchange for that, performance issues are raised because it is using Base64 approach.
6. Customization (disable Drag-and-Drop and Copy-and-Paste)
For some users, Drag-and-Drop or Copy-and-Paste operations may be handier than using Image uploader, but if there are any potential performance risks, I think we should do some systematic restrictions rather than just hoping that end users do not insert large images. I've raised an enhancement request (FDBK-96474) for this. If the size of image is small enough like 50KB, Base64 approach is acceptable, but some business type may require multiple higher resolution images (megabytes). In that case, Image uploader should be used. Since Drag-and-Drop and Copy-and-Paste in the current version uses Base64 approach, we have implemented a custom JavaScript to disable these operations so user is forced to use Image uploader. Pega RTE is an implementation of CKEditor and it is possible to customize the behavior per your business needs. Here are the steps.
6-1. Create a Text File rule
6-2. Copy and paste the below snippet.
pega.u.d.customRTEPlugins = pega.u.d.customRTEPlugins || {};
pega.u.d.customRTEPlugins["DisableDirectImagePaste"] = {
init: function(editor) {
function replaceImgText(html) {
var ret = html.replace(/<img[^>]*src="data:image\/(bmp|dds|gif|jpg|jpeg|png|psd|pspimage|tga|thm|tif|tiff|yuv|ai|eps|ps|svg);base64,.*?"[^>]*>/gi, function(img) {
alert("Direct image paste is not allowed.\nPlease use Image uploader in the toolbar.");
return '';});
return ret;
}
function chkImg() {
// do not execute code if the editor is readOnly
if(editor.readOnly) return;
setTimeout(function() {
editor.document.$.body.innerHTML = replaceImgText(editor.document.$.body.innerHTML);
}, 100);
}
editor.on( 'contentDom', function() {
// For Firefox Chrome
editor.document.on('drop', function(e) {chkImg(editor);});
// For IE
editor.document.getBody().on('drop', function(e) {chkImg(editor);});
// For Firefox Chrome
editor.document.on( 'paste', function(e) {chkImg(editor);});
// For IE
editor.document.getBody().on('paste', function(e) {chkImg(editor);});
});
}
}
6-3. Include this code in the Perform Harness.
6-4. That’s it. Now system prevents both Drag-and-Drop and Copy-and-Paste operations. I've verified that this code works on Chrome, Edge, and Firefox.
- Notes
Just for your reference, below is the initial simpler code that we developed. This can disable Drag-and-Drop, but Copy-and-Paste is still allowed. Also, restriction is applied not only for images but any Drag-and-Drop (Drag-and-Drop for Microsoft Word text, image, and table should be still allowed). We want to restrict Drag-and-Drop for only images, so prior code is probably better.
pega.u.d.customRTEPlugins = pega.u.d.customRTEPlugins || {};
pega.u.d.customRTEPlugins["DisableDragAndDrop"] = {
init: function(editor) {
editor.on('instanceReady', function(e) {
CKEDITOR.plugins.clipboard.preventDefaultDropOnElement(e.editor.document);
});
}
}
Hope this helps.
Thanks,