code: public static void zipRfsFolder(final File root, final OutputStream zipOutput) throws Exception {
  
          final ZipOutputStream zip = new ZipOutputStream(zipOutput);
          try {
              CmsFileUtil.walkFileSystem(root, new Closure() {
  
                  @SuppressWarnings("resource")
                  public void execute(Object stateObj) {
  
                      try {
                          FileWalkState state = (FileWalkState)stateObj;
                          for (File file : state.getFiles()) {
                              String relativePath = Paths.get(root.getAbsolutePath()).relativize(
                                  Paths.get(file.getAbsolutePath())).toString();
                              ZipEntry entry = new ZipEntry(relativePath);
                              entry.setTime(file.lastModified());
                              zip.putNextEntry(entry);
                              zip.write(CmsFileUtil.readFully(new FileInputStream(file)));
                              zip.closeEntry();
                          }
                      } catch (Exception e) {
                          throw new RuntimeException(e);
                      }
                  }
  
              });
          } catch (RuntimeException e) {
              if (e.getCause() instanceof Exception) {
                  throw (Exception)(e.getCause());
              } else {
                  throw e;
              }
  
          }
          zip.flush();
          zip.close();
  
      }
docs: Creates ZIP file data from the files / subfolders of the given root folder, and sends it to the given stream.<p>
  
  The stream passed as an argument is closed after the data is written.
  
  @param root the folder to zip
  @param zipOutput the output stream which the zip file data should be written to
  
  @throws Exception if something goes wrong