Browse Source

Refactor file generation methods to use TemporaryStorage for path management

Marcin Ziąbek 2 months ago
parent
commit
30f5b70b4a

+ 4 - 4
Source/QuestPDF/Fluent/GenerateExtensions.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 using QuestPDF.Drawing;
 using QuestPDF.Drawing;
+using QuestPDF.Helpers;
 using QuestPDF.Infrastructure;
 using QuestPDF.Infrastructure;
 using QuestPDF.Skia;
 using QuestPDF.Skia;
 
 
@@ -24,13 +25,12 @@ namespace QuestPDF.Fluent
         #region Genearate And Show Configuration
         #region Genearate And Show Configuration
 
 
         private static readonly Random Random = new();
         private static readonly Random Random = new();
-        private static string GetGenerateAndShowPath = Path.GetTempPath();
         private const string GenerateAndShowNamePrefix = "QuestPDF Preview";
         private const string GenerateAndShowNamePrefix = "QuestPDF Preview";
 
 
         private static void ClearGenerateAndShowFiles()
         private static void ClearGenerateAndShowFiles()
         {
         {
             var legacyPreviewFiles = Directory
             var legacyPreviewFiles = Directory
-                .GetFiles(GetGenerateAndShowPath, $"{GenerateAndShowNamePrefix} *")
+                .GetFiles(TemporaryStorage.GetPath(), $"{GenerateAndShowNamePrefix} *")
                 .Where(x => DateTime.UtcNow - new FileInfo(x).LastAccessTimeUtc > TimeSpan.FromHours(1));
                 .Where(x => DateTime.UtcNow - new FileInfo(x).LastAccessTimeUtc > TimeSpan.FromHours(1));
             
             
             foreach (var legacyPreviewFile in legacyPreviewFiles)
             foreach (var legacyPreviewFile in legacyPreviewFiles)
@@ -88,7 +88,7 @@ namespace QuestPDF.Fluent
         /// </summary>
         /// </summary>
         public static void GeneratePdfAndShow(this IDocument document)
         public static void GeneratePdfAndShow(this IDocument document)
         {
         {
-            var filePath = Path.Combine(GetGenerateAndShowPath, $"{GenerateAndShowNamePrefix} {Random.Next()}.pdf");
+            var filePath = Path.Combine(TemporaryStorage.GetPath(), $"{GenerateAndShowNamePrefix} {Random.Next()}.pdf");
             
             
             document.GeneratePdf(filePath);
             document.GeneratePdf(filePath);
             Helpers.Helpers.OpenFileUsingDefaultProgram(filePath);
             Helpers.Helpers.OpenFileUsingDefaultProgram(filePath);
@@ -150,7 +150,7 @@ namespace QuestPDF.Fluent
         /// </remarks>
         /// </remarks>
         public static void GenerateXpsAndShow(this IDocument document)
         public static void GenerateXpsAndShow(this IDocument document)
         {
         {
-            var filePath = Path.Combine(GetGenerateAndShowPath, $"{GenerateAndShowNamePrefix} {Random.Next()}.xps");
+            var filePath = Path.Combine(TemporaryStorage.GetPath(), $"{GenerateAndShowNamePrefix} {Random.Next()}.xps");
             document.GenerateXps(filePath);
             document.GenerateXps(filePath);
             Helpers.Helpers.OpenFileUsingDefaultProgram(filePath);
             Helpers.Helpers.OpenFileUsingDefaultProgram(filePath);
         }
         }

+ 68 - 0
Source/QuestPDF/Helpers/TemporaryStorage.cs

@@ -0,0 +1,68 @@
+using System;
+using System.IO;
+using System.Linq;
+
+namespace QuestPDF.Helpers;
+
+internal static class TemporaryStorage
+{
+    private static string? TemporaryStoragePath { get; set; }
+
+    internal static string GetPath()
+    {
+        var path = TryGetPath();
+
+        if (path == null)
+        {
+            throw new InvalidOperationException(
+                "Unable to find a suitable temporary storage location. " +
+                "Please specify it using the Settings.TemporaryStoragePath setting and ensure that the application has permissions to read and write to that location.");
+        }
+        
+        return path;
+    }
+    
+    internal static string? TryGetPath()
+    {
+        if (TemporaryStoragePath != null)
+            return TemporaryStoragePath;
+            
+        var candidates = new[]
+        {
+            Settings.TemporaryStoragePath,
+            Path.Combine(Path.GetTempPath(), "QuestPDF", "temp"),
+            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "QuestPDF", "temp"),
+            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "QuestPDF", "temp")
+        };
+
+        TemporaryStoragePath = candidates
+            .Where(x => x != null)
+            .FirstOrDefault(HasPermissionsToAlterPath);
+        
+        return TemporaryStoragePath;
+    }
+        
+    private static bool HasPermissionsToAlterPath(string path)
+    {
+        try
+        {
+            if (!Directory.Exists(path))
+                Directory.CreateDirectory(path);
+                
+            var testFile = Path.Combine(path, Path.GetRandomFileName());
+                
+            using (var fileStream = File.Create(testFile))
+            {
+                fileStream.WriteByte(123); // write anything
+            }
+                
+            File.Delete(testFile);
+                
+            return true;
+        }
+        catch
+        {
+            return false;
+        }
+    }
+}