To download multiple files use the DownloadsApi.createDownload method to create a ZIP download on the server side, then check the status of the ZIP download with DownloadsApi.getDownload. When the download is ready get it with NodesApi.getNodeConent. For more information, see Downloading a File.
For more information about this ReST API endpoint, see Download Multiple Files.
For a description of the common parameters, such as fields, see Common Parameters.
import org.alfresco.core.handler.DownloadsApi; import org.alfresco.core.handler.NodesApi; import org.alfresco.core.model.Download; import org.alfresco.core.model.DownloadBodyCreate; import org.alfresco.core.model.DownloadEntry; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; import java.io.File; import java.io.IOException; import java.time.OffsetDateTime; import java.util.List; @Component public class GetMultipleNodeContentCmd { static final Logger LOGGER = LoggerFactory.getLogger(GetMultipleNodeContentCmd.class); @Autowired DownloadsApi downloadsApi; @Autowired NodesApi nodesApi; public void execute(String[] fileNodeIds, String zipFilePathOnDisk) throws IOException, InterruptedException { DownloadEntry downloadEntry = createZipDownload(fileNodeIds); Resource zipNodeContent = getNodeContent(downloadEntry.getEntry().getId()); // Write ZIP file to disk File targetFile = new File(zipFilePathOnDisk); FileUtils.copyInputStreamToFile(zipNodeContent.getInputStream(), targetFile); } /** * Create a ZIP download with multiple file nodes. This method waits until download is ready. * * @param nodeIds the node ids for the files we want to download in one ZIP * @return download entry info object for the ZIP */ private DownloadEntry createZipDownload(String[] nodeIds) throws InterruptedException { List<String> fields = null; // Set up POST data with node IDs we want to download DownloadBodyCreate downloads = new DownloadBodyCreate(); for (String nodeId : nodeIds) { downloads.addNodeIdsItem(nodeId); } // First create the download on the server side DownloadEntry result = downloadsApi.createDownload(downloads, fields).getBody(); LOGGER.info("Created ZIP download: {}", result.getEntry().toString()); // Check the download status DownloadEntry download = downloadsApi.getDownload(result.getEntry().getId(), fields).getBody(); while (!download.getEntry().getStatus().equals(Download.StatusEnum.DONE)) { LOGGER.info("Checking ZIP download status: {}", download.getEntry().getStatus()); Thread.sleep(1000); // do nothing for 1000 milliseconds (1 second) download = downloadsApi.getDownload(result.getEntry().getId(), fields).getBody(); } LOGGER.info("ZIP download is READY: {}", result.getEntry().getId()); return download; } /** * Get a file node content bytes (folders does not have content). * * @param nodeId the id of the file node that we want to fetch content for. * @return Node content info object */ private Resource getNodeContent(String nodeId) throws IOException { // Relevant when using API call from web browser, true is the default Boolean attachment = true; // Only download if modified since this time, optional OffsetDateTime ifModifiedSince = null; // The Range header indicates the part of a document that the server should return. // Single part request supported, for example: bytes=1-10., optional String range = null; Resource result = nodesApi.getNodeContent(nodeId, attachment, ifModifiedSince, range).getBody(); LOGGER.info("Got node {} size: {}", result.getFilename(), result.contentLength()); return result; } }
Executing the code gives a result looking something like this:
% java -jar target/rest-api-0.0.1-SNAPSHOT.jar get-multiple-file-content 0492460b-6269-4ca1-9668-0d934d2f3370 48413f7a-066d-4e38-b2e6-c84ede635493 mydownload.zip 2021-04-29 12:58:53.560 INFO 19432 --- [ main] o.a.tutorial.restapi.RestApiApplication : Started RestApiApplication in 2.956 seconds (JVM running for 3.436) 2021-04-29 12:58:53.562 INFO 19432 --- [ main] o.a.tutorial.restapi.RestApiApplication : args[0]: get-multiple-file-content 2021-04-29 12:58:53.564 INFO 19432 --- [ main] o.a.tutorial.restapi.RestApiApplication : args[1]: 0492460b-6269-4ca1-9668-0d934d2f3370 2021-04-29 12:58:53.564 INFO 19432 --- [ main] o.a.tutorial.restapi.RestApiApplication : args[2]: 48413f7a-066d-4e38-b2e6-c84ede635493 2021-04-29 12:58:53.564 INFO 19432 --- [ main] o.a.tutorial.restapi.RestApiApplication : args[3]: mydownload.zip 2021-04-29 12:58:54.150 INFO 19432 --- [ main] o.a.t.restapi.GetMultipleNodeContentCmd : Created ZIP download: class Download { filesAdded: 0 bytesAdded: 0 id: b73c36e5-112b-48a0-baa6-fa225bd9d53d totalFiles: 0 totalBytes: 0 status: PENDING } 2021-04-29 12:58:54.167 INFO 19432 --- [ main] o.a.t.restapi.GetMultipleNodeContentCmd : Checking ZIP download status: PENDING 2021-04-29 12:58:55.194 INFO 19432 --- [ main] o.a.t.restapi.GetMultipleNodeContentCmd : ZIP download is READY: b73c36e5-112b-48a0-baa6-fa225bd9d53d 2021-04-29 12:58:55.223 INFO 19432 --- [ main] o.a.t.restapi.GetMultipleNodeContentCmd : Got node archive.zip size: 23111
In this example we pass in two file node identifiers that will be requested in the zip download. The zip download file will be stored in current directory under the name mydownload.zip. Note that right after we have initialized the creation of the zip download there are no files added to the zip (filesAdded: 0), we have to wait for the zip download to be created on the server side. Then we can download with the usual getNodeContent method. For more information, see Downloading a File.