/// <summary> /// The thing here is that we need to guarantee unique names at the top level, so we wrap the books inside a folder /// with some unique name. As this involves copying the folder it is also a convenient place to omit any PDF files /// except the one we want. /// </summary> public void UploadBook(string storageKeyOfBookFolder, string pathToBloomBookDirectory, IProgress progress, string pdfToInclude = null, ISet <string> audioFilesToInclude = null, IEnumerable <string> videoFilesToInclude = null, string[] languagesToInclude = null) { BaseUrl = null; BookOrderUrlOfRecentUpload = null; DeleteBookData(_bucketName, storageKeyOfBookFolder); // In case we're overwriting, get rid of any deleted files. //first, let's copy to temp so that we don't have to worry about changes to the original while we're uploading, //and at the same time introduce a wrapper with the last part of the unique key for this person+book string prefix = ""; // storageKey up to last slash (or empty) string tempFolderName = storageKeyOfBookFolder; // storage key after last slash (or all of it) // storageKeyOfBookFolder typically has a slash in it, email/id. // We only want the id as the temp folder name. // If there is anything before it, though, we want that as a prefix to make a parent 'folder' on parse.com. int index = storageKeyOfBookFolder.LastIndexOf('/'); if (index >= 0) { prefix = storageKeyOfBookFolder.Substring(0, index + 1); // must include the slash tempFolderName = storageKeyOfBookFolder.Substring(index + 1); } var wrapperPath = Path.Combine(Path.GetTempPath(), tempFolderName); //If we previously uploaded the book, but then had a problem, this directory could still be on our harddrive. Clear it out. if (Directory.Exists(wrapperPath)) { DeleteFileSystemInfo(new DirectoryInfo(wrapperPath)); } Directory.CreateDirectory(wrapperPath); var destDirName = Path.Combine(wrapperPath, Path.GetFileName(pathToBloomBookDirectory)); CopyDirectory(pathToBloomBookDirectory, destDirName); BookStorage.EnsureSingleHtmFile(destDirName); RemoveUnwantedVideoFiles(destDirName, videoFilesToInclude); ProcessVideosInTempDirectory(destDirName); RemoveUnwantedAudioFiles(destDirName, audioFilesToInclude); var unwantedPdfs = Directory.EnumerateFiles(destDirName, "*.pdf").Where(x => Path.GetFileName(x) != pdfToInclude); foreach (var file in unwantedPdfs) { RobustFile.Delete(file); } // Don't upload corrupt htms that have been repaired foreach (var path in Directory.EnumerateFiles(destDirName, BookStorage.PrefixForCorruptHtmFiles + "*.htm")) { RobustFile.Delete(path); } // Some more of the logic above might be useful to move into this method. BookStorage.RemoveLocalOnlyFiles(destDirName); if (languagesToInclude != null && languagesToInclude.Count() > 0) { RemoveUnwantedLanguageData(destDirName, languagesToInclude); } PublishHelper.ReportInvalidFonts(destDirName, progress); UploadDirectory(prefix, wrapperPath, progress); DeleteFileSystemInfo(new DirectoryInfo(wrapperPath)); }