jj: FileContainer Version 0.0.2

This commit is contained in:
Jonathan Jenne 2018-11-21 17:03:05 +01:00
parent 0f105b6ebf
commit 7b2ae3abc3
6 changed files with 190 additions and 241 deletions

View File

@ -3,7 +3,7 @@ Imports System.IO
Imports Microsoft.VisualStudio.TestTools.UnitTesting Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports DigitalData.Modules.Filesystem Imports DigitalData.Modules.Filesystem
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Filesystem.FileContainer Imports DigitalData.Modules.Filesystem.FileContainerOld
<TestClass()> Public Class FileContainerTest <TestClass()> Public Class FileContainerTest
@ -43,18 +43,18 @@ Imports DigitalData.Modules.Filesystem.FileContainer
<TestMethod()> <TestMethod()>
<ExpectedException(GetType(ArgumentNullException))> <ExpectedException(GetType(ArgumentNullException))>
Public Sub TestConstructorPasswordNothing() Public Sub TestConstructorPasswordNothing()
Dim oContainer = New FileContainer(_logConfig, Nothing) Dim oContainer = New FileContainerOld(_logConfig, Nothing)
End Sub End Sub
<TestMethod()> <TestMethod()>
Public Sub TestConstructorValidPassword() Public Sub TestConstructorValidPassword()
Dim oContainer = New FileContainer(_logConfig, "foobar") Dim oContainer = New FileContainerOld(_logConfig, "foobar")
End Sub End Sub
<TestMethod()> <TestMethod()>
<ExpectedException(GetType(FileNotFoundException))> <ExpectedException(GetType(FileNotFoundException))>
Public Sub TestAddFileNonExistentFilePath() Public Sub TestAddFileNonExistentFilePath()
Dim oContainer As New FileContainer(_logConfig, PASSWORD) Dim oContainer As New FileContainerOld(_logConfig, PASSWORD)
oContainer.AddFile(FILENAME_NONEXISTENT) oContainer.AddFile(FILENAME_NONEXISTENT)
End Sub End Sub
@ -62,21 +62,21 @@ Imports DigitalData.Modules.Filesystem.FileContainer
<TestMethod()> <TestMethod()>
<ExpectedException(GetType(ArgumentNullException))> <ExpectedException(GetType(ArgumentNullException))>
Public Sub TestAddFileNothingFilePath() Public Sub TestAddFileNothingFilePath()
Dim oContainer As New FileContainer(_logConfig, PASSWORD) Dim oContainer As New FileContainerOld(_logConfig, PASSWORD)
oContainer.AddFile(Nothing) oContainer.AddFile(Nothing)
End Sub End Sub
<TestMethod()> <TestMethod()>
Public Sub TestAddFileValidFilePath() Public Sub TestAddFileValidFilePath()
Dim oContainer As New FileContainer(_logConfig, PASSWORD) Dim oContainer As New FileContainerOld(_logConfig, PASSWORD)
oContainer.AddFile(FILENAME_VALID) oContainer.AddFile(FILENAME_VALID)
End Sub End Sub
<TestMethod()> <TestMethod()>
Public Sub TestFilesPropertyCount() Public Sub TestFilesPropertyCount()
Dim oContainer As New FileContainer(_logConfig, PASSWORD) Dim oContainer As New FileContainerOld(_logConfig, PASSWORD)
oContainer.AddFile(FILENAME_VALID) oContainer.AddFile(FILENAME_VALID)
Assert.AreEqual(1, oContainer.Files.Count) Assert.AreEqual(1, oContainer.Files.Count)
@ -84,7 +84,7 @@ Imports DigitalData.Modules.Filesystem.FileContainer
<TestMethod()> <TestMethod()>
Public Sub TestFilesPropertyType() Public Sub TestFilesPropertyType()
Dim oContainer As New FileContainer(_logConfig, PASSWORD) Dim oContainer As New FileContainerOld(_logConfig, PASSWORD)
oContainer.AddFile(FILENAME_VALID) oContainer.AddFile(FILENAME_VALID)
Assert.IsInstanceOfType(oContainer.Files.First(), GetType(FileEntry)) Assert.IsInstanceOfType(oContainer.Files.First(), GetType(FileEntry))
@ -93,7 +93,7 @@ Imports DigitalData.Modules.Filesystem.FileContainer
<TestMethod()> <TestMethod()>
Public Sub TestSaveValidPath() Public Sub TestSaveValidPath()
Dim oContainer As New FileContainer(_logConfig, PASSWORD) Dim oContainer As New FileContainerOld(_logConfig, PASSWORD)
oContainer.AddFile(FILENAME_VALID) oContainer.AddFile(FILENAME_VALID)
oContainer.Save(CONTAINER_FILE_VALID) oContainer.Save(CONTAINER_FILE_VALID)
@ -104,7 +104,7 @@ Imports DigitalData.Modules.Filesystem.FileContainer
<TestMethod()> <TestMethod()>
<ExpectedException(GetType(UnauthorizedAccessException))> <ExpectedException(GetType(UnauthorizedAccessException))>
Public Sub TestSavePathNotWritable() Public Sub TestSavePathNotWritable()
Dim oContainer As New FileContainer(_logConfig, PASSWORD) Dim oContainer As New FileContainerOld(_logConfig, PASSWORD)
oContainer.AddFile(FILENAME_VALID) oContainer.AddFile(FILENAME_VALID)
oContainer.Save(CONTAINER_FILE_NOWRITE) oContainer.Save(CONTAINER_FILE_NOWRITE)
@ -112,13 +112,13 @@ Imports DigitalData.Modules.Filesystem.FileContainer
<TestMethod()> <TestMethod()>
Public Sub TestSaveLoadSameContents() Public Sub TestSaveLoadSameContents()
Dim oContainer As FileContainer Dim oContainer As FileContainerOld
Dim oFileContents As String = "dasisteintest" Dim oFileContents As String = "dasisteintest"
' Test String in Textdatei schreiben ' Test String in Textdatei schreiben
IO.File.WriteAllText(FILENAME_VALID, oFileContents) IO.File.WriteAllText(FILENAME_VALID, oFileContents)
oContainer = New FileContainer(_logConfig, PASSWORD) oContainer = New FileContainerOld(_logConfig, PASSWORD)
' Textdatei zu einem Container hinzufügen ' Textdatei zu einem Container hinzufügen
oContainer.AddFile(FILENAME_VALID) oContainer.AddFile(FILENAME_VALID)
@ -131,7 +131,7 @@ Imports DigitalData.Modules.Filesystem.FileContainer
IO.File.Delete(FILENAME_VALID) IO.File.Delete(FILENAME_VALID)
oContainer = Nothing oContainer = Nothing
oContainer = New FileContainer(_logConfig, PASSWORD) oContainer = New FileContainerOld(_logConfig, PASSWORD)
' Container wieder laden ' Container wieder laden
oContainer.Load(CONTAINER_FILE_VALID) oContainer.Load(CONTAINER_FILE_VALID)

View File

@ -8,12 +8,19 @@ Imports DigitalData.Modules.Logging
Friend Class Encryption Friend Class Encryption
' This constant is used to determine the keysize of the encryption algorithm in bits. ' This constant is used to determine the keysize of the encryption algorithm in bits.
' We divide this by 8 within the code below to get the equivalent number of bytes. ' We divide this by 8 within the code below to get the equivalent number of bytes.
Private Const KEYSIZE As Integer = 256 Private Const KEY_SIZE As Integer = 256
' This constant determines the number of iterations for the password bytes generation function. ' This constant determines the number of iterations for the password bytes generation function.
Private Const DERIVATION_ITERATIONS As Integer = 1000 Private Const DERIVATION_ITERATIONS As Integer = 1000
Private Const BLOCK_SIZE As Integer = 256
Private _paddingMode As PaddingMode = PaddingMode.Zeros
Private _cipherMode As CipherMode = CipherMode.CBC
Private ReadOnly _password As String Private ReadOnly _password As String
Private _logger As Logger Private _logger As Logger
Public Sub New(LogConfig As LogConfig, Password As String) Public Sub New(LogConfig As LogConfig, Password As String)
_logger = LogConfig.GetLogger() _logger = LogConfig.GetLogger()
@ -37,11 +44,12 @@ Friend Class Encryption
Dim oSaltStringBytes = Generate256BitsOfRandomEntropy() Dim oSaltStringBytes = Generate256BitsOfRandomEntropy()
Dim oIvStringBytes = Generate256BitsOfRandomEntropy() Dim oIvStringBytes = Generate256BitsOfRandomEntropy()
Using oPassword = New Rfc2898DeriveBytes(_password, oSaltStringBytes, DERIVATION_ITERATIONS) Using oPassword = New Rfc2898DeriveBytes(_password, oSaltStringBytes, DERIVATION_ITERATIONS)
Dim oKeyBytes = oPassword.GetBytes(KEYSIZE / 8) Dim oKeyBytes = oPassword.GetBytes(KEY_SIZE / 8)
Using oSymmetricKey = New RijndaelManaged() Using oSymmetricKey = New RijndaelManaged()
oSymmetricKey.BlockSize = 256 oSymmetricKey.BlockSize = BLOCK_SIZE
oSymmetricKey.Mode = CipherMode.CBC oSymmetricKey.Mode = _cipherMode
oSymmetricKey.Padding = PaddingMode.PKCS7 oSymmetricKey.Padding = _paddingMode
Using oEncryptor = oSymmetricKey.CreateEncryptor(oKeyBytes, oIvStringBytes) Using oEncryptor = oSymmetricKey.CreateEncryptor(oKeyBytes, oIvStringBytes)
Using oMemoryStream = New MemoryStream() Using oMemoryStream = New MemoryStream()
Using oCryptoStream = New CryptoStream(oMemoryStream, oEncryptor, CryptoStreamMode.Write) Using oCryptoStream = New CryptoStream(oMemoryStream, oEncryptor, CryptoStreamMode.Write)
@ -76,18 +84,18 @@ Friend Class Encryption
' Get the complete stream of bytes that represent: ' Get the complete stream of bytes that represent:
' [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] ' [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
' Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes. ' Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
Dim oSaltStringBytes = cipherTextBytesWithSaltAndIv.Take(KEYSIZE / 8).ToArray() Dim oSaltStringBytes = cipherTextBytesWithSaltAndIv.Take(KEY_SIZE / 8).ToArray()
' Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes. ' Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
Dim oIvStringBytes = cipherTextBytesWithSaltAndIv.Skip(KEYSIZE / 8).Take(KEYSIZE / 8).ToArray() Dim oIvStringBytes = cipherTextBytesWithSaltAndIv.Skip(KEY_SIZE / 8).Take(KEY_SIZE / 8).ToArray()
' Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string. ' Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
Dim oCipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((KEYSIZE / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((KEYSIZE / 8) * 2)).ToArray() Dim oCipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((KEY_SIZE / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((KEY_SIZE / 8) * 2)).ToArray()
Using oPassword = New Rfc2898DeriveBytes(_password, oSaltStringBytes, DERIVATION_ITERATIONS) Using oPassword = New Rfc2898DeriveBytes(_password, oSaltStringBytes, DERIVATION_ITERATIONS)
Dim oKeyBytes = oPassword.GetBytes(KEYSIZE / 8) Dim oKeyBytes = oPassword.GetBytes(KEY_SIZE / 8)
Using oSymmetricKey = New RijndaelManaged() Using oSymmetricKey = New RijndaelManaged()
oSymmetricKey.BlockSize = 256 oSymmetricKey.BlockSize = BLOCK_SIZE
oSymmetricKey.Mode = CipherMode.CBC oSymmetricKey.Mode = _cipherMode
oSymmetricKey.Padding = PaddingMode.PKCS7 oSymmetricKey.Padding = _paddingMode
Using oDecryptor = oSymmetricKey.CreateDecryptor(oKeyBytes, oIvStringBytes) Using oDecryptor = oSymmetricKey.CreateDecryptor(oKeyBytes, oIvStringBytes)
Using oMemoryStream = New MemoryStream(oCipherTextBytes) Using oMemoryStream = New MemoryStream(oCipherTextBytes)
Using oCryptoStream = New CryptoStream(oMemoryStream, oDecryptor, CryptoStreamMode.Read) Using oCryptoStream = New CryptoStream(oMemoryStream, oDecryptor, CryptoStreamMode.Read)

View File

@ -1,10 +1,10 @@
Imports System.IO Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
Imports ProtoBuf
''' <module>FileContainer</module> ''' <module>FileContainer</module>
''' <version>0.0.0.1</version> ''' <version>0.0.0.2</version>
''' <date>16.11.2018</date> ''' <date>21.11.2018</date>
''' <summary> ''' <summary>
''' File Container for securely saving files ''' File Container for securely saving files
''' </summary> ''' </summary>
@ -13,277 +13,191 @@ Imports DigitalData.Modules.Logging
''' </dependencies> ''' </dependencies>
''' <params> ''' <params>
''' LogConfig, DigitalData.Module.Logging.LogConfig ''' LogConfig, DigitalData.Module.Logging.LogConfig
''' A LogConfig object ''' A LogConfig object
''' Password, String
''' The Password to Encrypt
''' Path, String
''' The Path to save/load the container
''' </params> ''' </params>
''' <props>
''' </props>
''' <example> ''' <example>
'''
'''
'''
'''
''' dim oContainer = Container.Create(logConfig, "pass", "E:\some.container")
''' dim oContainer = Container.Load(logConfig, "pass", "E:\some.container")
'''
''' dim oContainer = new Container(logConfig, "pass", "E:\some.container")
''' oContainer.Save()
'''
''' dim oContainer = new Container(logConfig, "pass", "E:\some.container")
''' oContainer.Contents = oSomeData
''' oContainer.Save()
'''
''' dim oContainer = new Container(logConfig, "pass", "E:\some.container")
''' oContainer.Load()
''' dim oContents = oContainer.Contents
'''
''' dim oContainer = new Container(logConfig, "pass", "E:\some.container")
''' oContainer.Load()
''' oContainer.Contents = oSomeOtherData
''' oContainer.Save()
''' oContainer.SaveAs("E:\some2.container")
''' </example> ''' </example>
''' <remarks>
''' </remarks>
Public Class FileContainer Public Class FileContainer
Private _files As List(Of FileEntry)
Private _crypto As Encryption Private _crypto As Encryption
Private _compression As Compression Private _compression As Compression
Private _formatter As BinaryFormatter
Private _containerId As Guid Private _containerId As Guid
Private _inner As FileContainerInner Private _inner As FileContainerInner
Private _logger As Logger Private _logger As Logger
Private _logConfig As LogConfig Private _logConfig As LogConfig
Private _path As String
<Serializable> Public Property Contents As Byte()
Public Class FileEntry
Public FileId As String
Public Contents As Byte()
Public CreatedAt As DateTime
Public UpdatedAt As DateTime
End Class
<Serializable>
Public Class FileContainerInner
Public Files As List(Of FileEntry)
Public ContainerID As Guid
Public CreatedAt As DateTime
Public UpdatedAt As DateTime
End Class
Public ReadOnly Property ContainerId As String
Get Get
If _inner Is Nothing Then Return _inner.Contents
Return Nothing End Get
End If Set(value As Byte())
_inner.Contents = value
Return _inner.ContainerID.ToString End Set
End Property
Public Property Extension As String
Get
Return _inner.Extension
End Get
Set(value As String)
_inner.Extension = value
End Set
End Property
Public ReadOnly Property FileId As String
Get
Return _inner.FileId
End Get
End Property
Public ReadOnly Property CreatedAt As String
Get
Return _inner.CreatedAt
End Get
End Property
Public ReadOnly Property UpdatedAt As String
Get
Return _inner.UpdatedAt
End Get End Get
End Property End Property
''' <summary> Public Shared Function Create(LogConfig As LogConfig, Password As String) As FileContainer
''' Gibt eine Auflistung der Dateien in Container zurück. Dim oContainer = New FileContainer(LogConfig, Password)
''' </summary> Return oContainer
''' <returns>Eine Liste von Objekten der Klasse FileContainer.FileEntry</returns> End Function
Public ReadOnly Property Files As List(Of FileEntry)
Get
If _inner Is Nothing Then
Return Nothing
End If
Return _inner.Files Public Shared Function Load(LogConfig As LogConfig, Password As String, Path As String) As FileContainer
End Get Dim oContainer = New FileContainer(LogConfig, Password, Path)
End Property oContainer.Load()
Return oContainer
End Function
Public Sub New(LogConfig As LogConfig, Password As String, Path As String)
_logger = LogConfig.GetLogger()
_crypto = New Encryption(LogConfig, Password)
_compression = New Compression(LogConfig)
_inner = New FileContainerInner()
_path = Path
End Sub
''' <summary>
''' Erstellt eine Representation eines Datei Containers, der mit dem angegebenen Passwort geschützt ist.
''' Ist für das speichern von neuen Containern und für das laden vorhandener Container nötig.
''' </summary>
''' <param name="Password">Das Passwort, mit dem der Container ver- und entschlüsselt wird</param>
''' <example>
''' Dim password = "meinpasswort"
''' Dim container = new FileContainer(password)
''' </example>
Public Sub New(LogConfig As LogConfig, Password As String) Public Sub New(LogConfig As LogConfig, Password As String)
_logger = LogConfig.GetLogger() _logger = LogConfig.GetLogger()
_crypto = New Encryption(LogConfig, Password) _crypto = New Encryption(LogConfig, Password)
_compression = New Compression(LogConfig) _compression = New Compression(LogConfig)
_formatter = New BinaryFormatter _inner = New FileContainerInner()
_inner = New FileContainerInner() With {
.Files = New List(Of FileEntry),
.ContainerID = Guid.NewGuid(),
.CreatedAt = New DateTime()
}
End Sub End Sub
''' <summary> Public Sub SetFile(Contents As Byte(), Extension As String)
''' Speichert einen Datei Container am angegebenen Pfad. _inner.Contents = Contents
''' Davor werden die Dateien in Files komprimiert und dann verschlüsselt. _inner.Extension = Extension
''' </summary> End Sub
''' <param name="Path">Der Pfad mit Dateiname, unter dem der Container abgelegt wird.</param>
''' <see cref="Files"/>
''' <example>
''' container.AddFile("datei1.txt")
''' container.AddFile("datei2.pdf")
''' container.Save("container.enc")
''' </example>
Public Sub Save(Path As String)
Try
' 1. Serialize
Dim oFileContainerInner As Byte() = Serialize(_inner)
' 2. Compress
Dim oFileContainerCompressed As Byte() = _compression.Compress(oFileContainerInner)
' 3. Encrypt
Dim oFileContainerEncrypted As Byte() = _crypto.Encrypt(oFileContainerCompressed)
BytesToFile(oFileContainerEncrypted, Path) Public Sub Save()
If IsNothing(_path) Then
Throw New ArgumentException("Path not set")
End If
SaveAs(_path)
End Sub
Public Sub SaveAs(Path As String)
Try
WriteBytesToFile(TransformToBytes(_inner), Path)
Catch ex As Exception Catch ex As Exception
_logger.Error(ex) _logger.Error(ex)
Throw ex Throw ex
End Try End Try
End Sub End Sub
''' <summary> Public Sub Load()
''' Speichert einen Datei Container am angegebenen Pfad. If IsNothing(_path) Then
''' Davor werden die Dateien in Files komprimiert und dann verschlüsselt. Throw New ArgumentException("Path not set")
''' </summary> End If
''' <param name="Path">Der Pfad mit Dateiname, unter dem der Container abgelegt wird.</param>
''' <example> LoadFrom(_path)
''' Public Async Sub foobar() End Sub
''' ...
''' container.AddFile("datei1.txt") Public Sub LoadFrom(Path As String)
''' container.AddFile("datei2.pdf")
''' await container.SaveAsync("container.enc")
''' ...
''' End Sub
''' </example>
Public Async Function SaveAsync(Path As String) As Task
Try Try
' 1. Serialize _inner = TransformToObject(ReadBytesFromFile(_path))
Dim oFileContainerInner As Byte() = Serialize(_inner)
' 2. Compress
Dim oFileContainerCompressed As Byte() = Await _compression.CompressAsync(oFileContainerInner)
'Dim bFilesCompressed = bFiles
' 3. Encrypt
Dim oFileContainerEncrypted As Byte() = Await _crypto.EncryptAsync(oFileContainerCompressed)
BytesToFileAsync(oFileContainerEncrypted, Path)
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
''' <summary>
''' Lädt einen Datei Container aus dem angegebenen Pfad.
''' Anschließend werden die enthaltenen Dateien entschlüsselt, dekomprimiert und in Files abgelegt.
''' </summary>
''' <param name="Path">Der Pfad mit Dateiname, von dem der Container geladen wird.</param>
''' <see cref="Files"/>
''' <example>
''' container.Load("container.enc")
''' Dim files As List(Of FileContainer.FileEntry) = container.Files
''' </example>
Public Sub Load(Path As String)
Try
Dim oContainerInnerEncrypted As Byte() = FileToBytes(Path)
' 1. Decrypt
Dim oFileContainerCompressed As Byte() = _crypto.Decrypt(oContainerInnerEncrypted)
' 2. Decompress
Dim oFileContainerInner As Byte() = _compression.Decompress(oFileContainerCompressed)
' 3. Deserialize
_inner = Deserialize(oFileContainerInner)
Catch ex As Exception Catch ex As Exception
_logger.Error(ex) _logger.Error(ex)
Throw ex Throw ex
End Try End Try
End Sub End Sub
''' <summary> Private Function TransformToBytes([Object] As FileContainerInner) As Byte()
''' Lädt einen Datei Container aus dem angegebenen Pfad. Dim oBytes = Serialize([Object])
''' Anschließend werden die enthaltenen Dateien entschlüsselt, dekomprimiert und in Files abgelegt. Dim oCompressed = _compression.Compress(oBytes)
''' </summary> Dim oEncrypted = _crypto.Encrypt(oCompressed)
''' <param name="Path">Der Pfad mit Dateiname, von dem der Container geladen wird.</param> Return oEncrypted
''' <example>
''' Public Async Sub foobar()
''' ...
''' await container.LoadAsync("container.enc")
''' Dim files As List(Of FileContainer.FileEntry) = container.Files
''' ...
''' End Sub
''' </example>
Public Async Function LoadAsync(Path As String) As Task
Try
Dim oContainerInnerEncrypted As Byte() = Await FileToBytesAsync(Path)
' 1. Decrypt
Dim oFileContainerCompressed As Byte() = Await _crypto.DecryptAsync(oContainerInnerEncrypted)
' 2. Decompress
Dim oFileContainerInner As Byte() = Await _compression.DecompressAsync(oFileContainerCompressed)
' 3. Deserialize
_inner = Deserialize(oFileContainerInner)
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function End Function
''' <summary> Private Function TransformToObject(Bytes As Byte()) As FileContainerInner
''' Fügt einem Datei Container eine neue Datei hinzu Dim oDecrypted = _crypto.Decrypt(Bytes)
''' </summary> Dim oDecompressed = _compression.Decompress(oDecrypted)
''' <param name="FilePath">Der Pfad zur Datei, die im Container gespeichert werden soll</param> Dim oObject = Deserialize(oDecompressed)
''' <exception cref="FileNotFoundException" /> Return oObject
Public Function AddFile(FilePath As String) As String
Try
Dim oFileInfo As New FileInfo(FilePath)
If oFileInfo.Exists = False Then
Throw New FileNotFoundException($"{FilePath} is not a valid path.")
End If
Return AddFileAsByteArray(IO.File.ReadAllBytes(FilePath))
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
Public Function AddFileAsByteArray(FileContents As Byte()) As String
Try
Dim oFileEntry As New FileEntry With {
.Contents = FileContents,
.FileId = Guid.NewGuid().ToString()
}
_inner.Files.Add(oFileEntry)
Return oFileEntry.FileId
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
Public Function GetFile(FileId As String) As FileEntry
Return _inner.Files.Where(Function(f) f.FileId = FileId).FirstOrDefault()
End Function End Function
Private Function Serialize(InnerData As FileContainerInner) As Byte() Private Function Serialize(InnerData As FileContainerInner) As Byte()
Dim oBinaryData As Byte()
Using oStream As New MemoryStream Using oStream As New MemoryStream
_formatter.Serialize(oStream, InnerData) Serializer.Serialize(oStream, InnerData)
Return oStream.ToArray() oBinaryData = oStream.ToArray()
End Using End Using
Return oBinaryData
End Function End Function
Private Function Deserialize(InnerData As Byte()) As FileContainerInner Private Function Deserialize(InnerData As Byte()) As FileContainerInner
Dim oObject As FileContainerInner
Using oStream As New MemoryStream(InnerData) Using oStream As New MemoryStream(InnerData)
Dim oInner = TryCast(_formatter.Deserialize(oStream), FileContainerInner) oObject = Serializer.Deserialize(Of FileContainerInner)(oStream)
Return oInner
End Using End Using
Return oObject
End Function End Function
Private Sub BytesToFile(Data As Byte(), FilePath As String) Private Sub WriteBytesToFile(Data As Byte(), FilePath As String)
Using oSourceStream As New FileStream(FilePath, FileMode.Append, FileAccess.Write, FileShare.None) Using oSourceStream As New FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
oSourceStream.Write(Data, 0, Data.Length) oSourceStream.Write(Data, 0, Data.Length)
oSourceStream.Flush() oSourceStream.Flush()
End Using End Using
End Sub End Sub
Private Function FileToBytes(FilePath As String) As Byte() Private Function ReadBytesFromFile(FilePath As String) As Byte()
Return IO.File.ReadAllBytes(FilePath) Using oFileStream = New FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096)
End Function
Private Async Function FileToBytesAsync(FilePath As String) As Task(Of Byte())
Using oFileStream = New FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, True)
Dim oBuffer As Byte() = New Byte(oFileStream.Length - 1) {} Dim oBuffer As Byte() = New Byte(oFileStream.Length - 1) {}
Await oFileStream.ReadAsync(oBuffer, 0, oFileStream.Length) oFileStream.Read(oBuffer, 0, oFileStream.Length)
oFileStream.Close() oFileStream.Close()
Return oBuffer Return oBuffer
End Using End Using
End Function End Function
Private Async Sub BytesToFileAsync(Data As Byte(), FilePath As String)
Using oSourceStream As New FileStream(FilePath, FileMode.Append, FileAccess.Write, FileShare.None, 4096, True)
Await oSourceStream.WriteAsync(Data, 0, Data.Length)
Await oSourceStream.FlushAsync()
End Using
End Sub
End Class End Class

View File

@ -0,0 +1,22 @@
Imports ProtoBuf
<Serializable>
<ProtoContract>
Public Class FileContainerInner
<ProtoMember(1)>
Public FileId As String
<ProtoMember(2)>
Public Contents As Byte()
<ProtoMember(3)>
Public CreatedAt As DateTime
<ProtoMember(4)>
Public UpdatedAt As DateTime
<ProtoMember(5)>
Public Extension As String
Public Sub New()
FileId = Guid.NewGuid.ToString
CreatedAt = Date.Now
End Sub
End Class

View File

@ -47,6 +47,9 @@
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.5.10\lib\net45\NLog.dll</HintPath> <HintPath>..\packages\NLog.4.5.10\lib\net45\NLog.dll</HintPath>
</Reference> </Reference>
<Reference Include="protobuf-net, Version=2.4.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
<HintPath>..\packages\protobuf-net.2.4.0\lib\net40\protobuf-net.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Configuration" /> <Reference Include="System.Configuration" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
@ -73,9 +76,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Compression.vb" /> <Compile Include="Compression.vb" />
<Compile Include="FileContainer.vb" />
<Compile Include="Encryption.vb" /> <Compile Include="Encryption.vb" />
<Compile Include="File.vb" /> <Compile Include="File.vb" />
<Compile Include="FileContainer.vb" /> <Compile Include="FileContainerInner.vb" />
<Compile Include="My Project\AssemblyInfo.vb" /> <Compile Include="My Project\AssemblyInfo.vb" />
<Compile Include="My Project\Application.Designer.vb"> <Compile Include="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="NLog" version="4.5.10" targetFramework="net461" /> <package id="NLog" version="4.5.10" targetFramework="net461" />
<package id="protobuf-net" version="2.4.0" targetFramework="net461" />
</packages> </packages>