0

I have a requirement, which I should merge two or more word files (.docx) together into one file.

because I can't do arithmetic operations on Blob - I converted it to hex, made the arithmetic, converted it to blob again, and then I tried to save it inside the versionData.

But it saves only the first doc and not both.

I tried to do the following : (the hardcoded Ids is just for testing)

 List<ContentVersion> cdlList =  [SELECT Id,Title,ContentDocumentId,FileType,VersionData FROM ContentVersion WHERE ContentDocumentId='0691l000001DoBTAA0' OR ContentDocumentId='0691l000001DoE3AAK'];
 List<ContentVersion> cvList = new List<ContentVersion>();    
 String combinedDataAsHex = EncodingUtil.convertToHex(cdlList[0].VersionData) + EncodingUtil.convertToHex(cdlList[1].VersionData);
 ContentVersion testContentInsert = new ContentVersion();
 testContentInsert.Title = 'Test';
 testContentInsert.VersionData = EncodingUtil.convertFromHex(combinedDataAsHex);
 testContentInsert.PathOnClient = '/' + cdlList[0].title + '.docx' ;
 cvList.add(testContentInsert);

    
    
 insert cvList;

Is there something I missed? Another way to do it?

Thanks.

3
  • 2
    In many, perhaps most, cases, concatenating the raw contents of two files is not equivalent to merging the files' user-facing content. You need to actually get into the content of the files and their structure, which is not impossible but is challenging in Apex. You'll find some examples of people manipulating the XLSX and/or DOCX file formats if you search SFSE.
    – David Reed
    Commented Dec 15, 2020 at 21:00
  • 2
    I really doubt concatenating two hex strings together will produce a valid binary file format. Most file formats have explicit start and end points which is likely what you are running into with your two DOCX files. Once the file parser encounters the end indicator, it stops reading. So even if the content for the other file is stored inside the first, DOCX readers are going to ignore it. I would look into the DOCX file format and see how feasible it is to do this. A DOCX is essentially an archive with an XML file that dictates where all the components fit together.
    – nbrown
    Commented Dec 15, 2020 at 21:07
  • Thanks guys for the extra information.
    – Salvation
    Commented Dec 16, 2020 at 9:05

1 Answer 1

5

Aside from plain text files (e.g. source code or README.TXT type files), most files follow an internal structure. This means that two similar files (e.g. two GIF or DOCX) being "added together" would result in an invalid file structure. Let me give you an example using plain text; we'll choose XML.

File A

<?xml version="1.0" encoding="UTF-8"?>
<request>
  <param1>Hello World</param1>
</request>

File B

<?xml version="1.0" encoding="UTF-8"?>
<request>
  <param2>Goodbye World</param2>
</request>

If you were to combine these two files together as you demonstrated in your question, the result would be:

<?xml version="1.0" encoding="UTF-8"?>
<request>
  <param1>Hello World</param1>
</request>
<?xml version="1.0" encoding="UTF-8"?>
<request>
  <param2>Goodbye World</param2>
</request>

But this isn't valid XML. There must be only one preprocessor command, and one root element. The correct file would be:

<?xml version="1.0" encoding="UTF-8"?>
<request>
  <param1>Hello World</param1>
  <param2>Goodbye World</param2>
</request>

You can't get this by just adding one file to the other, you need to understand the internal structure and adapt.

Similarly, to get two DOCX to work as one, you'd have to decompress both (they're ZIP files), unpack the XML files, recombine, recompress (back to a single ZIP), and then output that result.

This is technically possible in Apex, but you're much better off shipping the files offsite to a Heroku app or something, where you'll have much better CPU performance and fewer restraints, plus actual binary support that Apex is notorious for lacking.

1
  • Thank you. Great example and explanation.
    – Salvation
    Commented Dec 16, 2020 at 9:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .