Skip to Content
Technical Articles
Author's profile photo Yusuf Adiputera

How to Enable Image Upload in Backoffice WYSIWYG editor


SAP Commerce’s Backoffice uses CKEditor 4 as a WYSIWYG editor. Out of the box, CKEditor does support file/image upload, we just need to provide the API for file/image upload, although it’s not enabled by default.

By default, the image dialog in the backoffice WYSIWYG editor is like this, you can only insert images by URL, with no option for upload, note that “Tautan” is “Link“:


Backoffice WYSIWYG default image dialog

In this blog post, I will guide you on how to enable image upload in the backoffice WYSIWYG editor.


You need to have some basic knowledge of SAP Commerce and its extensions.

The Steps

  1. First, you need to know the response CKEditor is expecting, and the response is like this if the upload is a success:
        "fileName": "filename.png",
        "uploaded": 1,
        "url": "{urlOfTheMedia}"

    And if the upload is failing, the response CKEditor expecting is like this:

        "error": {
          "message": "some error message, return this if upload is failed"
        "uploaded": 0
  2. Based on the JSON in the first step, create a new DTO by adding this in the trainingwebservices-beans.xml:
    <bean class="">
    	<property name="message" type="String"/>
    <bean class="">
    	<property name="uploaded" type="Integer"/>
    	<property name="fileName" type="String"/>
    	<property name="url" type="String"/>
    	<property name="error" type=""/>
  3. Create a new controller that will accept the “upload” parameter with the type of MultipartFile and save it as a CatalogUnawareMedia
    @ApiOperation(nickname = "uploadFile", value = "Upload a file. by Yusuf F. Adiputera")
    public ResponseEntity<FileUploadResponseDTO> uploadImageFile(@ApiParam("File to upload") @RequestParam("upload") final MultipartFile upload)
        FileUploadResponseDTO responseDTO = new FileUploadResponseDTO();
        try {
            CatalogUnawareMediaModel mediaModel = modelService.create(CatalogUnawareMediaModel.class);
            mediaModel.setCode("images" + "-" + System.currentTimeMillis() + upload.getOriginalFilename());
            mediaService.setStreamForMedia(mediaModel, upload.getInputStream(),
                        upload.getOriginalFilename(), upload.getContentType());
            return new ResponseEntity<>(responseDTO, HttpStatus.ACCEPTED);
        } catch (Exception e) {
            LOGGER.error("An error occurred while saving media: {}", e.getMessage(), e);
            MessageDTO messageDTO = new MessageDTO();
            return new ResponseEntity<>(responseDTO, HttpStatus.BAD_REQUEST);
  4. Create a new filter for file upload in {webservicesextension}/web/src/
     * The class FileUploadFilter
     * @author Yusuf F. Adiputera
    public class FileUploadFilter extends AbstractUrlMatchingFilter {
        private Map<String, MultipartFilter> urlFilterMapping;
        private PathMatcher pathMatcher;
        public void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
                                     final FilterChain filterChain) throws IOException, ServletException
            if (
                final MultipartFilter multipartFilter = getMultipartFilter(request.getServletPath());
                if (multipartFilter != null)
                    multipartFilter.doFilter(request, response, filterChain);
                    filterChain.doFilter(request, response);
                filterChain.doFilter(request, response);
        protected MultipartFilter getMultipartFilter(final String servletPath)
            for (Map.Entry<String, MultipartFilter> multipartFilterEntry : getUrlFilterMapping().entrySet())
                if (getPathMatcher().match(multipartFilterEntry.getKey(), servletPath))
                    return multipartFilterEntry.getValue();
            return null;
        protected Map<String, MultipartFilter> getUrlFilterMapping()
            return urlFilterMapping;
        public void setUrlFilterMapping(final Map<String, MultipartFilter> urlFilterMapping)
            this.urlFilterMapping = urlFilterMapping;
        protected PathMatcher getPathMatcher()
            return pathMatcher;
        public void setPathMatcher(final PathMatcher pathMatcher)
            this.pathMatcher = pathMatcher;
  5. Register previous filter as bean inside {webservicesextension}/web/webroot/WEB-INF/config/v2/filter-config-v2-spring.xml
    <bean id="occAntPathMatcher" class="org.springframework.util.AntPathMatcher" />
    <bean id="occFileUploadFilter" class="" >
    	<property name="urlFilterMapping">
    		<ref bean="occFileUploadUrlFilterMappings" />
    	<property name="pathMatcher" ref="occAntPathMatcher"/>
    <alias name="defaultOccFileUploadUrlFilterMappings" alias="occFileUploadUrlFilterMappings" />
    <util:map id="defaultOccFileUploadUrlFilterMappings" key-type="java.lang.String" value-type="">
    	<entry key="/**" value-ref="occMultiPartFilter"/>
    <bean id="occMultiPartFilter" class="">
    	<property name="multipartResolverBeanName" value="occMultipartResolver"/>
    <bean id="occMultipartResolver"

    Then add occFileUploadFilter in the FilterChainList

    <alias name="defaultCommerceWebServicesFilterChainListV2" alias="commerceWebServicesFilterChainListV2" />
    <util:list id="defaultCommerceWebServicesFilterChainListV2">
    	<!-- some other filter -->
    	<!-- ................. -->
    	<!-- filter to handle multipart file upload -->
    	<ref bean="occFileUploadFilter" />
  6. Create a new file, named customckeditorconfig.js in {backofficeextension}/backoffice/resources/cng/customckeditorconfig.js
    CKEDITOR.editorConfig = function(config) {
    	// replace this with your file upload URL
    	config.filebrowserImageUploadUrl = '/trainingwebservices/v2/training/file-upload';
  7.  Add this line inside {backofficeextension}/ so CKEditor can read the config:
  8. Build the application by executing ant all
  9. Test the API from the Postman
  10. Open Backoffice, open any WYSISYG editor and check if there’s a new “upload” tab. Note in this picture “Unggah” is “Upload“, “Tautan” is “Link
  11. Test Uploading an image by going to the “Upload” tab, click “Choose file” to browse for files, and click “Send to server” to upload
    The image will be uploaded, you can change the height, and width if you’d like, then click ok
    Successfully%20upload%20an%20imageThe image will be added to the WYSIWYG editor
  12. Done


The API will be open without any authentication since the webservices extension can’t read the backoffice sessions, so if the webservices endpoint is exposed to the public, everyone will be able to upload some files without any authentication.

Please let me know in the comment if you have any feedback or any questions. You might also check other blogs about SAP Commerce or SAP Commerce Cloud.

Or you might want to check on SAP Commerce or SAP Commerce Cloud topic.

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.