internal async Task <RepositoryPackageResult> GetPackageInternal(string packageId, string archiveRecordId, bool createMetadataXml,
                                                                         List <string> fileTypesToIgnore, int primaerdatenAuftragId)
        {
            Debug.Assert(fileTypesToIgnore != null, "fileTypesToIgnore must not be null");

            // Init the return value
            var retVal = new RepositoryPackageResult
            {
                Success        = false,
                Valid          = false,
                PackageDetails = new RepositoryPackage {
                    ArchiveRecordId = archiveRecordId
                }
            };
            var currentStatus = AufbereitungsStatusEnum.AuftragGestartet;

            try
            {
                var allIgnoredFiles = new List <RepositoryFile>();
                var rootFolder      = repositoryDataAccess.GetRepositoryRoot(packageId);
                if (rootFolder != null)
                {
                    var tempRootFolder = GetTempRootFolder();
                    var zipFileName    = GetZipFileName(tempRootFolder);

                    try
                    {
                        var watch = Stopwatch.StartNew();
                        Log.Information("Fetching the metadata for package with id {packageId}", packageId);

                        // Get the metadata about the packages
                        retVal.PackageDetails.PackageId = packageId;
                        retVal.PackageDetails.Folders   = repositoryDataAccess.GetFolders(rootFolder.Id);
                        retVal.PackageDetails.Files     = repositoryDataAccess.GetFiles(rootFolder.Id, ignoredFilenameRegex, out var ignored);
                        allIgnoredFiles.AddRange(ignored);

                        // Get the sub folders of the root folders
                        foreach (var folder in retVal.PackageDetails.Folders)
                        {
                            GetFolderContent(folder, allIgnoredFiles);
                        }

                        if (allIgnoredFiles.Count > 0)
                        {
                            Log.Information("We have found {fileCount} files to ignore. These are: {files}", allIgnoredFiles.Count,
                                            JsonConvert.SerializeObject(allIgnoredFiles));
                        }

                        // Ensure valid file names and prevent too long paths and file names
                        packageValidator.EnsureValidPhysicalFileAndFolderNames(retVal.PackageDetails,
                                                                               Path.Combine(tempRootFolder, contentFolderName));

                        // Now create a folder and file structure on disk matching the metadata
                        Log.Information("Creating package structure on disk for package with id {packageId}", packageId);
                        LogFreeDiskSpace(packageId);
                        CreatePackageOnDisk(tempRootFolder, retVal.PackageDetails, fileTypesToIgnore);
                        LogFreeDiskSpace(packageId);

                        // Create the metadata.xml
                        if (createMetadataXml)
                        {
                            handler.CreateMetadataXml(Path.Combine(tempRootFolder, headerFolderName), retVal.PackageDetails, allIgnoredFiles);
                        }

                        // Get some information about the package
                        var numberOfFilesInZipFile =
                            Directory.GetFiles(Path.Combine(tempRootFolder, contentFolderName), "*.*", SearchOption.AllDirectories).Length;
                        var sizeInBytes       = GetSizeInBytesFromMetadata(retVal.PackageDetails, false);
                        var sizeInBytesOnDisk = Directory.GetFiles(tempRootFolder, "*.*", SearchOption.AllDirectories)
                                                .Select(f => new FileInfo(f).Length).Sum();
                        var numberOfFilesInMetadata =
                            GetFileCountFromMetadata(retVal.PackageDetails, false); // Get all files according to DIR metadata
                        var numberOfFilesInMetadataRespectingIgnored =
                            GetFileCountFromMetadata(retVal.PackageDetails, true);  // Get all files not counting the ignored ones
                        Log.Information("Package with id {packageId} has size {SizeInBytes:n0} bytes", packageId, sizeInBytes);

                        currentStatus = AufbereitungsStatusEnum.PrimaerdatenExtrahiert;
                        await UpdatePrimaerdatenAuftragStatus(primaerdatenAuftragId, currentStatus);

                        // Make a zip file
                        ZipFile.CreateFromDirectory(tempRootFolder, zipFileName);
                        Log.Information("ZipFile created for package with id {packageId}", packageId);
                        LogFreeDiskSpace(packageId);

                        currentStatus = AufbereitungsStatusEnum.ZipDateiErzeugt;
                        await UpdatePrimaerdatenAuftragStatus(primaerdatenAuftragId, currentStatus);

                        // Check if package is valid.
                        // Number of files must correspond. In case of just getting the files for OCR, the createMetadataXml is false and number of files is counted differently
                        var isValidPackage = numberOfFilesInMetadata == numberOfFilesInZipFile ||
                                             !createMetadataXml && numberOfFilesInZipFile == numberOfFilesInMetadataRespectingIgnored;

                        var fi = new FileInfo(zipFileName);
                        if (isValidPackage)
                        {
                            // Copy the zip file to the final destination.
                            // Depending on the setting either by sftp or a simple file copy
                            if (Settings.Default.UseSFTP)
                            {
                                CopyBySftp(fi);
                            }
                            else
                            {
                                MoveFileToDestination(fi);
                            }
                        }

                        // Delete zip file. If it was moved it is already gone, so we check
                        if (fi.Exists)
                        {
                            fi.Delete();
                        }

                        // Construct the result
                        retVal.PackageDetails.FileCount       = numberOfFilesInMetadata;
                        retVal.PackageDetails.SizeInBytes     = sizeInBytes;
                        retVal.PackageDetails.PackageFileName = fi.Name;

                        // Adjust the download time with an estimated download speed
                        retVal.PackageDetails.RepositoryExtractionDuration =
                            watch.ElapsedTicks + GetProcessingTimeOfIgnoredFilesInTicks(sizeInBytes - sizeInBytesOnDisk);
                        retVal.Success = true;
                        retVal.Valid   = isValidPackage;

                        currentStatus = AufbereitungsStatusEnum.PaketTransferiert;
                        await UpdatePrimaerdatenAuftragStatus(primaerdatenAuftragId, currentStatus);

                        if (!retVal.Valid)
                        {
                            var metadata = JsonConvert.SerializeObject(retVal.PackageDetails);
                            Log.Error(
                                "Have {numberOfFilesInZipFile} files in package, but should be {numberOfFilesInMetadata} files according to metadata. Metadata is {metadata}",
                                numberOfFilesInZipFile,
                                numberOfFilesInMetadata, metadata);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Unknown error while creating the package with id {packageId}.", packageId);
                        LogFreeDiskSpace(packageId);

                        // Do we have a stry zip file? (out of space exception while zipping...)
                        if (File.Exists(zipFileName))
                        {
                            Log.Information("Found remains of zip file. Deleting zip file {zipFileName} for package {packageId}.", zipFileName,
                                            packageId);
                            File.Delete(zipFileName);
                            Log.Information("Deleted zip file {zipFileName} for package {packageId}.", zipFileName, packageId);
                        }

                        retVal.ErrorMessage = $"Unknown error: {ex.Message}.";
                        while (ex.InnerException != null)
                        {
                            retVal.ErrorMessage += Environment.NewLine + ex.InnerException.Message;
                            ex = ex.InnerException;
                        }
                    }
                    finally
                    {
                        // Delete the temp files
                        Directory.Delete(tempRootFolder, true);
                        Log.Information("Deleted temp files for package {packageId}", packageId);
                    }
                }
                else
                {
                    Log.Warning("Could not find package with id {packageId} in the repository", packageId);
                    retVal.ErrorMessage = $"Could not find package with id {packageId} in the repository";
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Failed to get package with id {packageId} from repository", packageId);
                LogFreeDiskSpace(packageId);
                retVal.ErrorMessage = "Failed to get package from repository";
            }

            // Bei einem Fehlerfall melden wir den letzten Status erneut, diesmal mit ErrorText an die Priorisierungsengine
            if (!retVal.Success)
            {
                await UpdatePrimaerdatenAuftragStatus(primaerdatenAuftragId, currentStatus, retVal.ErrorMessage);
            }

            return(retVal);
        }