diff --git a/src/UniversalFiles/IUFileProvider.cs b/src/UniversalFiles/IUFileProvider.cs
index 4cef673..2c4ec5c 100644
--- a/src/UniversalFiles/IUFileProvider.cs
+++ b/src/UniversalFiles/IUFileProvider.cs
@@ -12,10 +12,18 @@
// You should have received a copy of the GNU Lesser General Public License along with UniversalFiles.
// If not, see .
+using System.Threading.Tasks;
+
namespace Etherna.UniversalFiles
{
public interface IUFileProvider
{
UFile BuildNewUFile(UUri uuri);
+
+ Task ToLocalUFileAsync(
+ UFile inputUFile,
+ UUriKind allowedUriKinds = UUriKind.All,
+ string? baseDirectory = null,
+ BasicUUri? outputUUri = null);
}
}
\ No newline at end of file
diff --git a/src/UniversalFiles/UFileProvider.cs b/src/UniversalFiles/UFileProvider.cs
index 4799d7b..95f7fc8 100644
--- a/src/UniversalFiles/UFileProvider.cs
+++ b/src/UniversalFiles/UFileProvider.cs
@@ -14,7 +14,9 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Net.Http;
+using System.Threading.Tasks;
namespace Etherna.UniversalFiles
{
@@ -39,5 +41,36 @@ public UFile BuildNewUFile(UUri uuri)
public void RegisterUUriType(Func builder) where TUUri : UUri =>
uFileBuilders[typeof(TUUri)] = uuri => builder((TUUri)uuri);
+
+ public async Task ToLocalUFileAsync(
+ UFile inputUFile,
+ UUriKind allowedUriKinds = UUriKind.All,
+ string? baseDirectory = null,
+ BasicUUri? outputUUri = null)
+ {
+ ArgumentNullException.ThrowIfNull(inputUFile, nameof(inputUFile));
+
+ // If it's already a local file, skip file retrieve.
+ if (inputUFile is BasicUFile basicUFile &&
+ (basicUFile.FileUri.UriKind & allowedUriKinds & UUriKind.Local) != 0)
+ return basicUFile;
+
+ if (outputUUri != null && outputUUri.UriKind != UUriKind.LocalAbsolute)
+ throw new InvalidOperationException("If provided, output uuri must be local and absolute");
+
+ if (outputUUri is null)
+ {
+ var fileName = await inputUFile.TryGetFileNameAsync().ConfigureAwait(false);
+ outputUUri = fileName is null ?
+ new BasicUUri(Path.GetTempFileName()) :
+ new BasicUUri(Path.Join(Path.GetTempPath(), fileName));
+ }
+
+ using var inputFileStream = (await inputUFile.ReadToStreamAsync(allowedUriKinds, baseDirectory).ConfigureAwait(false)).Stream;
+ using var outputFileStream = new FileStream(outputUUri.ToAbsoluteUri().Item1, FileMode.Create);
+ await inputFileStream.CopyToAsync(outputFileStream).ConfigureAwait(false);
+
+ return (BasicUFile)BuildNewUFile(outputUUri);
+ }
}
}
\ No newline at end of file