Imports System.Data.SqlClient Imports DigitalData.Modules.Base.IDB.Constants Imports DigitalData.Modules.Database Imports DigitalData.Modules.Database.MSSQLServer.TransactionMode Imports DigitalData.Modules.Logging Namespace Methods.IDB.NewFile Public Class NewFileMethod Inherits BaseMethod Private ReadOnly Connection As SqlConnection Private ReadOnly Transaction As SqlTransaction Public Sub New(pLogConfig As LogConfig, pDatabaseIDB As MSSQLServer, pDatabaseECM As MSSQLServer, pGlobalState As GlobalState) MyBase.New(pLogConfig, pDatabaseIDB, pDatabaseECM, pGlobalState) Connection = DatabaseIDB.GetConnection() Transaction = Connection.BeginTransaction() End Sub Public Function Run(pData As NewFileRequest) As NewFileResponse Logger.Debug("Running [NewFileMethod].") Dim oFilePath As String = Nothing Try If pData.File Is Nothing Then Throw New ArgumentNullException(NameOf(pData.File)) End If If pData.KindType Is Nothing Then Throw New ArgumentNullException(NameOf(pData.KindType)) End If If pData.StoreName Is Nothing Then Throw New ArgumentNullException(NameOf(pData.StoreName)) End If If pData.User Is Nothing Then Throw New ArgumentNullException(NameOf(pData.User)) End If If IsNothing(pData.IDBDoctypeId) Then Throw New ArgumentNullException(NameOf(pData.IDBDoctypeId)) End If Logger.Debug("Checking if checksum already exists..") Dim oExistingObjectId = Helpers.TestFileChecksumExists(pData.File.FileChecksum) If oExistingObjectId > 0 Then Return New NewFileResponse(oExistingObjectId) End If Logger.Debug("Creating New ObjectId..") Dim oObjectId = Helpers.NewObjectIdWithTransaction(pData.KindType, pData.User.UserName, Connection, Transaction) If oObjectId = 0 Then LogAndThrow("Could not create new ObjectId!") End If Logger.Debug("New ObjectId [{0}] created!", oObjectId) ' Find ObjectStore by Title Logger.Debug("Checking for DataStore [{0}].", pData.StoreName) Dim oStore = GlobalState.ObjectStores. Where(Function(store) store.Title = pData.StoreName). SingleOrDefault() If oStore Is Nothing Then LogAndThrow($"DataStore [{pData.StoreName}] does not exist. Exiting.") End If Logger.Debug("Using DataStore [{0}].", pData.StoreName) ' Get Store base and final path Logger.Debug("Store BasePath is [{0}]", oStore.Path) Dim oFinalPath = Helpers.GetFileObjectPath(oStore, pData.File.FileImportedAt) ' Get filename Dim oKeepFileName As Boolean = False If oStore.IsArchive Then Logger.Debug("Object Store is an archive: [{0}]", oStore.IsArchive) oKeepFileName = True End If Dim oFileName As String = GetFileObjectFileName(oObjectId, pData.File.FileName, oKeepFileName) Logger.Debug("Filename is [{0}]", oFileName) oFilePath = IO.Path.Combine(oFinalPath, oFileName) Dim oFileObjectInfo As IO.FileInfo = New IO.FileInfo(oFilePath) Dim oFileObjectName As String = oFileObjectInfo.Name Logger.Debug("File Information for [{0}]:", oFileObjectName) Dim oFileObjectSize As Long = pData.File.FileContents.Length Logger.Debug("Size: [{0}]", oFileObjectSize) Dim oOriginalExtension As String = pData.File.FileInfoRaw.Extension.Substring(1) Logger.Debug("Original Extension: [{0}]", oOriginalExtension) Logger.Debug("Checksum: [{0}]", pData.File.FileChecksum) Try Using oStream = New IO.FileStream(oFilePath, IO.FileMode.Create, IO.FileAccess.Write) Logger.Info("Saving file to path [{0}]", oFilePath) oStream.Write(pData.File.FileContents, 0, oFileObjectSize) oStream.Flush(True) oStream.Close() End Using Catch ex As Exception LogAndThrow(ex, $"Could not write file [{oFilePath}] to disk!") End Try '--------------------------------------------------------------------------- Logger.Info("Creating IDB FileObject for ObjectId [{0}].", oObjectId) ' Insert into DB Dim oSQL As String = $"EXEC PRIDB_NEW_IDBFO '{oFinalPath}', '{oFileObjectName}', '{oOriginalExtension}', {oFileObjectSize}, '{pData.File.FileChecksum}' , '{pData.User.UserName}', '{oObjectId}', {oStore.Id}, {pData.IDBDoctypeId}" Dim oResult As Boolean = DatabaseIDB.ExecuteNonQueryWithConnectionObject(oSQL, Connection, ExternalTransaction, Transaction) If oResult = False Then LogAndThrow("IDB FileObject could not be created!") End If '--------------------------------------------------------------------------- Dim oSystemAttributes As New Dictionary(Of String, Object) From { {Attributes.ATTRIBUTE_ORIGIN_FILENAME, pData.File.FileName}, {Attributes.ATTRIBUTE_ORIGIN_CREATED, pData.File.FileCreatedAt}, {Attributes.ATTRIBUTE_ORIGIN_CHANGED, pData.File.FileChangedAt} } For Each oAttribute As KeyValuePair(Of String, Object) In oSystemAttributes Try ' Dont write empty attributes If oAttribute.Value Is Nothing Then Continue For End If Dim oSuccess = Helpers.SetAttributeValueWithTransaction(Connection, Transaction, oObjectId, oAttribute.Key, oAttribute.Value, pData.User.Language, pData.User.UserName) If oSuccess Then Logger.Debug("System Attribute [{0}] written with value [{1}]", oAttribute.Key, oAttribute.Value) Else Logger.Warn("System attribute value could not be written") End If Catch ex As Exception LogAndThrow(ex, $"System attribute [{oAttribute.Key}] could not be written!") End Try Next '--------------------------------------------------------------------------- ' Finally, commit the transaction Transaction?.Commit() Return New NewFileResponse(oObjectId) Catch ex As Exception Logger.Warn("Error occurred while creating file!") Logger.Error(ex) Logger.Info("Cleaning up files.") If Not IsNothing(oFilePath) AndAlso IO.File.Exists(oFilePath) Then Try IO.File.Delete(oFilePath) Catch exInner As Exception Logger.Warn("Error while cleaning up files.") Logger.Error(exInner) End Try End If Logger.Info("Rolling back transaction.") Transaction?.Rollback() Return New NewFileResponse(ex) End Try End Function Private Function GetFileObjectFileName(IDB_OBJ_ID As Long, pFilename As String, pKeepFilename As Boolean) As String ' TODO: save actual extensions If pKeepFilename Then Return pFilename Else Return $"{IDB_OBJ_ID}.ddfo" End If End Function End Class End Namespace