Imports Microsoft.VisualBasic Imports System Imports System.IO Imports DevExpress.Xpo Imports System.ComponentModel Imports DevExpress.Persistent.Base Imports DevExpress.Persistent.BaseImpl Imports DevExpress.Persistent.Validation 'Dennis: the FileDataEx class allows you to store files in file system instead of the database. You can set the required path in the DefaultDirectory constant. _ Public Class FileDataEx Inherits BaseObject Implements IFileData, IEmptyCheckable Public Const DefaultDirectory As String = "D:\Store\" Private Const ReadBytesSize As Integer = &H1000 Private tempStream As Stream = Nothing Private tempFileName As String = String.Empty _ Private _Size As Integer _ Public ReadOnly Property Size() As Integer Implements IFileData.Size Get Return _Size End Get End Property Public Sub New(ByVal session As Session) MyBase.New(session) End Sub Public Overrides Function ToString() As String Return FileName End Function Private _Content() As Byte _ Public Property Content() As Byte() Get Return _Content End Get Set(ByVal value As Byte()) SetPropertyValue("Content", _Content, value) End Set End Property _ Public ReadOnly Property IsEmpty() As Boolean Implements IEmptyCheckable.IsEmpty Get Return String.IsNullOrEmpty(_FileName) AndAlso Not Exists End Get End Property Public Overrides Sub AfterConstruction() MyBase.AfterConstruction() If (Not Directory.Exists(DefaultDirectory)) Then Directory.CreateDirectory(DefaultDirectory) End If End Sub Private _FileName As String = String.Empty _ Public Property FileName() As String Implements IFileData.FileName Get Return _FileName End Get Set(ByVal value As String) SetPropertyValue("FileName", _FileName, value) End Set End Property Public ReadOnly Property RealFileName() As String Get If _FileName <> String.Empty Then Return Path.Combine(DefaultDirectory, GetUniqueFileName(_FileName)) Else Return String.Empty End If End Get End Property Protected Overridable Function GetUniqueFileName(ByVal shortFileName As String) As String Return String.Format("{0}-{1}", Oid, shortFileName) End Function Protected Overridable Function GetShortFileName(ByVal uniqueFileName As String) As String Return uniqueFileName.Replace(String.Format("{0}-", Oid), String.Empty).Replace(DefaultDirectory, String.Empty) End Function Public ReadOnly Property Exists() As Boolean Get Return File.Exists(RealFileName) End Get End Property 'Dennis: fires when assigning a file. Public Sub LoadFromStream(ByVal fileName As String, ByVal source As Stream) Implements IFileData.LoadFromStream tempStream = source 'Dennis: when assigning a new file we need to save the name of the old file to remove it from the store in the future. If String.IsNullOrEmpty(tempFileName) Then tempFileName = RealFileName End If Me.FileName = fileName End Sub 'Dennis: fires when saving or opening a file. Public Sub SaveToStream(ByVal destination As Stream) Implements IFileData.SaveToStream Try Using source As Stream = File.OpenRead(RealFileName) Dim buffer(ReadBytesSize - 1) As Byte Dim read As Integer = 0 read = source.Read(buffer, 0, buffer.Length) Do While read > 0 destination.Write(buffer, 0, read) read = source.Read(buffer, 0, buffer.Length) Loop End Using Catch exc As DirectoryNotFoundException Throw New Exception(String.Format("Cannot access the '{0}' store because it is not available.", DefaultDirectory), exc) Catch exc As FileNotFoundException Throw New Exception(String.Format("Cannot access the '{0}' file because it is not found in the store.", FileName), exc) End Try End Sub Protected Overrides Sub OnSaving() MyBase.OnSaving() If tempStream IsNot Nothing AndAlso (Not String.IsNullOrEmpty(RealFileName)) Then Dim source As Stream = Nothing 'Dennis: for Windows Forms applications. If TypeOf tempStream Is FileStream Then Try source = File.OpenRead((CType(tempStream, FileStream)).Name) Catch exc As FileNotFoundException Throw New Exception(String.Format("Cannot read the '{0}' file from a temporary store.", FileName), exc) End Try Else 'Dennis: for Web Forms applications. source = tempStream End If Try Using destination As Stream = File.OpenWrite(RealFileName) Dim buffer(ReadBytesSize - 1) As Byte Dim read As Integer = 0 read = source.Read(buffer, 0, buffer.Length) Do While read > 0 destination.Write(buffer, 0, read) read = source.Read(buffer, 0, buffer.Length) Loop UpdateSize(destination) End Using Catch exc As DirectoryNotFoundException Throw New Exception(String.Format("Cannot access the '{0}' store because it is not available.", DefaultDirectory), exc) Finally source.Close() source = Nothing End Try End If 'Dennis: removing the old file from the store when saving the current object. If (Not String.IsNullOrEmpty(tempFileName)) Then Try File.Delete(tempFileName) tempFileName = String.Empty Catch exc As DirectoryNotFoundException Throw New Exception(String.Format("Cannot access the '{0}' store because it is not available.", DefaultDirectory), exc) End Try End If End Sub Protected Overrides Sub OnDeleting() 'Dennis: first we need to remove the old file from the store. Clear() MyBase.OnDeleting() End Sub Private Sub UpdateSize(ByVal stream As Stream) If stream Is Nothing Then _Size = 0 Else _Size = CInt(Fix(stream.Length)) End If End Sub Public Sub Clear() Implements IFileData.Clear 'Dennis: when clearing the file name property we need to save the name of the old file to remove it from the store in the future. If String.IsNullOrEmpty(tempFileName) Then tempFileName = RealFileName End If FileName = String.Empty UpdateSize(Nothing) End Sub End Class