File Attachments (Store Custom Files)
- 7 minutes to read
XAF includes a File Attachments module and file data types for file management (upload, download, open, and save files). This module contains Property Editors and Controllers for the file data type.
#Supported Functionality
#ASP NET Core Blazor
FileDataPropertyEditor
displays the property’s value as a link with the file name. A user can click the link to download the file. The Detail View, displays the Select File and Clear buttons. A user should save changes after a file is uploaded to display a link instead of a plain text file name.
FileDataPropertyEditor
shows upload progress. The default maximum file size is 4 MB. Use the FileAttachmentsOptions.DefaultMaxFileSize property to change the default value.
FileAttachmentsBlazorModule
splits the file into chunks and uploads them to the server.
#Windows Forms
- Attach a File
- When a user clicks the ellipsis button on the
FileDataPropertyEditor
, the application invokes the OpenFileDialog dialog, which you can use to select an attached file. - Save an Attached File to a Disk
- The
FileDataPropertyEditor
context menu contains the SaveTo Action. TheFileAttachmentController.SaveFileData
method handles this Action’sExecute
event. You can override this method in theFileAttachmentController
descendant to change the default logic. - Open an Attached File
- The
FileDataPropertyEditor
context menu contains the Open Action. TheFileAttachmentController.Open
method handles this Action’sExecute
event. You can override this method in theFileAttachmentController
descendant to change the default logic. - Detach a File
- The
FileDataPropertyEditor
context menu contains the ClearContent Action. This Action’sExecute
event handler calls the property type’sClear
method to clear file content. Override the IFileData.Clear method to implement your logic.
#ASP.NET Web Forms
FileDataPropertyEditor
displays the FileDataEdit
control, which shows a different set of controls in View and Edit modes:
- View Mode
Displays the
HtmlAnchor
control that allows users to download the current file.- Edit Mode
FileDataPropertyEditor
shows ASPxButtons Change File and Clear buttons (xref:DevExpress.Web.ASPxButton).XAF calls the property type’s
Clear
method to make the Clear button to clear property values. You can override the IFileData.Clear method to implement your logic.The Change File button makes ASPxUploadControl visible to allow users to upload a new file.
A user can click the
HtmlAnchor
control with the file name to download the file.Default maximum file size is 4 MB.
#File Attachments Module Components
The following table contains classes for different platforms:
Platform | Module Class | Nu |
---|---|---|
ASP. |
| DevExpress. |
Win | DevExpress. | |
ASP. | DevExpress. |
The File Attachments Module contains the following Property Editors to display file data properties in the UI:
DevExpress.ExpressApp.FileAttachment.Blazor.FileDataPropertyEditor
DevExpress.ExpressApp.FileAttachment.Win.FileDataPropertyEditor
DevExpress.ExpressApp.FileAttachment.Web.FileDataPropertyEditor
#Add the File Attachments Module to an XAF Application
Install the appropriate platform-specific NuGet package and use one of the following techniques to add the File Attachments Module:
You can add modules to your application when you use the Solution Wizard to create a new XAF solution. Select modules in the Choose Additional Modules step.
In .NET applications, you can call the AddFileAttachments(IModuleBuilder<IWinApplicationBuilder>, Action<FileAttachmentsOptions>) method in your ASP.NET Core Blazor/WinForms application builder.
- Alternatively, you can add these Modules to the ModuleBase.RequiredModuleTypes collection of the platform-specific Module.
- In .NET Framework applications, you can also use the Module Designer and Application Designer to add a module to your project.
#Entity Framework Core-Based Application
The following additional step is required if you use Entity Framework Core:
Navigate to the YourSolutionName.Module\BusinessObjects\YourSolutionNameDbContext.cs file and include the
FileData
entity in the data model:C#using DevExpress.Persistent.BaseImpl.EF; // ... public class YourSolutionNameEFCoreDbContext : DbContext { // ... public DbSet<FileData> FileData { get; set; } // ... }
#Define a File Data Object and Storage
The file data object is a business class that implements the IFileData interface. You can also use the built-in FileData
class (XPO: the %PROGRAMFILES%\DevExpress 24.1\Components\Sources\DevExpress.Persistent\DevExpress.Persistent.BaseImpl\FileData.cs file, EF Core: the %PROGRAMFILES%\DevExpress 24.1\Components\Sources\DevExpress.Persistent\DevExpress.Persistent.BaseImpl.EF\FileData.cs file).
using DevExpress.Persistent.Base;
namespace MySolution.Module.BusinessObjects {
[FileAttachmentAttribute(nameof(File))]
public class MyFileAttachment : BaseObject {
// ...
[ExpandObjectMembers(ExpandObjectMembers.Never)]
[FileTypeFilter("DocumentFiles", 1, "*.txt", "*.doc")]
[FileTypeFilter("AllFiles", 2, "*.*")]
public virtual FileData File { get; set; }
}
public class FileData : BaseObject, IFileData {
// ...
}
}
// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
Refer to the following help topic for more information on file data properties: File Attachment Properties.
XAF stores attached files in a database in a binary form. When you use the DevExpress.Persistent.BaseImpl.FileData
type, the gzip compression is applied to a file. Maximum file size is 2 GB.
#Upload and Download File Attachments Programmatically (in Code)
Call the IFileData.LoadFromStream method to upload a file in code. To obtain the file, call the IFileData.SaveToStream method. The LoadFromStream
method does not require a full path to the file. This method accepts a file name as the first parameter.
#Examples
Tip
The following example implements a business class with a file data property and a file collection property: How to: Implement File Data Properties.
#Read Compressed Files in the FileData Database Table from External Non-XAF .NET Applications
XAF stores attached files in a database in a binary form. Maximum file size is 2 GB. The XPO DevExpress.Persistent.BaseImpl.FileData
type compresses files when it adds them to the database and decompresses files when they are accessed in the database. The DevExpress.Persistent.Base.CompressionConverter
class (a custom XPO Value Converter class from the DevExpress.Persistent.BaseImpl.Xpo
assembly) applies GZIP compression to files. For more information on the GZIP compression algorithm, refer to the source code at %PROGRAMFILES%\DevExpress 24.1\Components\Sources\DevExpress.Persistent\DevExpress.Persistent.BaseImpl.Xpo\CompressionUtils.cs.
Use one of the following options to read compressed files in the FileData
database table from external non-XAF .NET apps:
If you can use XPO and
FileData
for data access, call the SaveToStream(Stream) method.Otherwise, call the
CompressionConverter.ConvertFromStorageType
method as shown below:C#using DevExpress.Data.Filtering; using DevExpress.Xpo; using SolutionName.Module.BusinessObjects; using System; using System.Data.SqlClient; using System.IO; using DevExpress.Persistent.Base; namespace SolutionName { class Program { static void Main(string[] args) { string cons = @"Integrated Security=SSPI;Pooling=false;Data Source=(localdb)\mssqllocaldb;Initial Catalog=XafDbWithFiles"; SqlConnection conn = new SqlConnection(cons); conn.Open(); SqlCommand sqlCmd = new SqlCommand("SELECT Content, FileName FROM FileData Where oid = 'B4C546BB-807D-4951-8443-50B800B6BE2D'", conn); using(SqlDataReader rdr = sqlCmd.ExecuteReader()) { while(rdr.Read()) { byte[] column1 =(byte[]) rdr["Content"]; var conv = new CompressionConverter(); byte[] decomp = (byte[]) conv.ConvertFromStorageType(column1); string column2 = rdr["FileName"].ToString(); using(var fs = new FileStream("c:\\test\\1ok_"+column2, FileMode.CreateNew)) { fs.Write(decomp, 0, decomp.Length); fs.Flush(); } } } conn.Close(); conn.Dispose(); } } }
If you do not want to reference the
DevExpress.Persistent.BaseImpl.Xpo
assembly, copy the source code of theCompressionConverter
class to your external non-XAF .NET project.If you do not need default file compression, you can create a custom IFileData implementation and use it instead of the
DevExpress.Persistent.BaseImpl.FileData
type in your application. To do this, copy the source code of theFileData.cs
class. You can find it in the %PROGRAMFILES%\DevExpress 24.1\Components\Sources\DevExpress.Persistent\DevExpress.Persistent.BaseImpl.Xpo folder. In the copied code, remove the[ValueConverter(typeof(CompressionConverter))]
line from theContent
property, and rename the class and namespaces.