Hopefully this can save you some work. It uses a much larger chunk size (which is a multiple of 57) and works with or without CR/LFs (set the argument pAddCRLF):

Class Example.B64.Util Extends %RegisteredObject

/// Be cautious if changing CHUNKSIZE. Incorrect values could cause the resulting encoded data to be invalid.
/// It should always be a multiple of 57 and needs to be less than ~2.4MB when MAXSTRING is 3641144
Parameter CHUNKSIZE = 2097144;

ClassMethod B64EncodeStream(pStream As %Stream.Object, pAddCRLF As %Boolean = 0) As %Stream.Object
    set tEncodedStream=##class(%Stream.GlobalCharacter).%New()
    do pStream.Rewind()
    while ('pStream.AtEnd) {
        set tReadLen=..#CHUNKSIZE
        set tChunk=pStream.Read(.tReadLen)
        do tEncodedStream.Write($System.Encryption.Base64Encode(tChunk,'pAddCRLF))
        if (pAddCRLF && 'pStream.AtEnd) {
            do tEncodedStream.Write($c(13,10))
    do tEncodedStream.Rewind()
    quit tEncodedStream


My experience with Zebras was quite a few years ago, so this may or may not still apply... Using Zen reports at the time, the print server would end up rendering the label as a bitmap and sending that over to the Zebra. ZPL code to print an equivalent label was much smaller than a bitmap, so ZPL labels tended to print faster than those rendered by a report.