411 File upload and download of ABP framework applications - chempkovsky/CS82ANGULAR GitHub Wiki

Note
  • To work with files, it is enough to declare an entity with a property of the string-type and [DataType(DataType.Upload)]-attribute. This property will be used to story a file-name in the database.
  • The first important requirement is that this property must be part of the primary key, since it is not possible to create two files with the same name in the repository (for instabce, in the same folder of the file system).
  • Secondly, you cannot define the update method. The only add and delete methods are implemented.
Entity
  • In the Phbk folder of the rupbes.firstapp.Domain.csproj project, create a class as shown below. We have composite primary key which inludes FlNm.
Click to show the code
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;

namespace rupbes.firstapp.Phbk
{
    public class PhbkFile : BasicAggregateRoot, IMultiTenant, IHasConcurrencyStamp
    {
        [Display(Description = "File Id", Name = "File Id", Prompt = "Enter File Id", ShortName = "File Id")]
        [Required]
        public virtual int FileId { get; protected set; } = default!;

        [Display(Description = "File Name", Name = "File Name", Prompt = "Enter File Name", ShortName = "File Name")]
        [StringLength(72, MinimumLength = 1, ErrorMessage = "Invalid")]
        [DataType(DataType.Upload)]
        [Required]
        public virtual string FlNm { get; protected set; } = default!;

        [DisableAuditing]
        [Display(Description = "Concurrency Stamp", Name = "Concurrency Stamp", Prompt = "Enter Concurrency Stamp", ShortName = "Concurrency Stamp")]
        [StringLength(40, MinimumLength = 0, ErrorMessage = "Invalid")]
        [Required]
        [ConcurrencyCheck]
        public virtual string ConcurrencyStamp { get; set; } = default!;

        [Display(Description = "Tenant id", Name = "Tenant Id", Prompt = "Enter Tenant Id", ShortName = "Tenant Id")]
        public virtual Guid? TenantId { get; protected set; }

        public PhbkFile() : base()
        {
            ConcurrencyStamp = Guid.NewGuid().ToString("N");
        }

        public PhbkFile(int fileId, string flNm) : base()
        {
            FileId = fileId;
            FlNm = flNm;
            ConcurrencyStamp = Guid.NewGuid().ToString("N");
        }

        public override object[] GetKeys()
        {
            return new object[] { FileId, FlNm };
        }

    }
}
Modify DBContext
Click to show the code
    protected override void OnModelCreating(ModelBuilder builder)
    {

#if (!NOTMODELING)
        builder.Entity<PhbkFile>().HasKey(p => new { p.FileId, p.FlNm });
        builder.Entity<PhbkPhoneType>().HasKey(p => p.Id);
#endif
        base.OnModelCreating(builder);
        /* Include modules to your migration db context */
        builder.ConfigurePermissionManagement();
        builder.ConfigureSettingManagement();
        builder.ConfigureBackgroundJobs();
        builder.ConfigureAuditLogging();
        builder.ConfigureFeatureManagement();
        builder.ConfigureIdentity();
        builder.ConfigureOpenIddict();
        builder.ConfigureTenantManagement();
        builder.ConfigureBlobStoring();
        /* Configure your own tables/entities inside here */
        //builder.Entity<YourEntity>(b =>
        //{
        //    b.ToTable(firstappConsts.DbTablePrefix + "YourEntities", firstappConsts.DbSchema);
        //    b.ConfigureByConvention(); //auto configure for the base class props
        //    //...
        //});
        builder.ConfigurefirstappDbContext();
    }
  • ConfigurefirstappDbContext must be as follows:
    public static class firstappDbContextCreatingExtensions
    {
        public static void ConfigurefirstappDbContext(
            this ModelBuilder builder)
        {
            Check.NotNull(builder, nameof(builder));

            builder.Entity<PhbkPhoneType>(b =>
            {
                b.ToTable(firstappConsts.DbTablePrefix + "PhbkPhoneTypes", firstappConsts.DbSchema);
                b.ConfigureByConvention(); //auto configure for the base class props
                                           //...
                builder.Entity<PhbkPhoneType>().HasKey(p => p.Id);
            });
            builder.Entity<PhbkFile>(b =>
            {
                b.ToTable(firstappConsts.DbTablePrefix + "PhbkFiles", firstappConsts.DbSchema);
                b.ConfigureByConvention(); //auto configure for the base class props
                                           //...
                builder.Entity<PhbkFile>().HasKey(p => new { p.FileId, p.FlNm });
            });
        }
    }
Dto
Click to show the picture

project structure

Web Api
Click to show the picture

project structure

  • After generation code open the file PhbkFileDtoWebApiController.cs. At the begining of the file you will find the instructions:
Click to show the code
/*
...

  // == 3 ==
  // read this: https://docs.abp.io/en/abp/latest/Blob-Storing
  // 3.1. add "Volo.Abp.BlobStoring" package to the ".csproj"-file
  // 3.2. add [DependsOn(typeof(AbpBlobStoringModule))] to the ABP module class inside your project.
  // create a class  "PhbkFileDtoBlobContainer" like seen
  //
    [BlobContainerName("phbk-file-dto")]
    public class PhbkFileDtoBlobContainer {}
    


  // 3.3.create this class in the same folder as for the "PhbkFileDtoService"-class
  // 3.3.in the project XXX.HttpApi.Host.csproj
  //        in the module class 
  //           in the "ConfigureServices"-method write something like seen below:

    public override void ConfigureServices(ServiceConfigurationContext context)
    {
...
        Configure<AbpBlobStoringOptions>(options =>
        {
            options.Containers.Configure("phbk-file-dto", container =>
            {
                container.IsMultiTenant = false; // or true
                container.UseFileSystem(fileSystem =>
                {
                    fileSystem.BasePath = "C:\\temp\phbk-file-dto"; // or any folder you like or use something like this configuration["AbpBlobStoringOptions:PhbkFileDto"]
                });
            });
        });

...
    }  
*/

So in the Controllers-folder of the rupbes.firstapp.HttpApi.csproj-project create a class:

Click to show the code
using Volo.Abp.BlobStoring;

namespace rupbes.firstapp.Controllers
{
    [BlobContainerName("phbk-file-dto")]
    public class PhbkFileDtoBlobContainer { }
}
  • In the ItemGroup of rupbes.firstapp.HttpApi.csproj-project add a reference onto Volo.Abp.BlobStoring-package. In our case it is Version="9.1.0". Make sure to install the correct version of the package, as the version may be different in your case. It depends on the version of abp installed on your computer.
Click to show the code
  <ItemGroup>
    <PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" Version="9.1.0" />
    <PackageReference Include="Volo.Abp.FeatureManagement.HttpApi" Version="9.1.0" />
    <PackageReference Include="Volo.Abp.SettingManagement.HttpApi" Version="9.1.0" />

    <PackageReference Include="Volo.Abp.BlobStoring" Version="9.1.0" />
  </ItemGroup>
  • Modify DependsOn-attribute of the firstappHttpApiModule-class of the rupbes.firstapp.HttpApi.csproj-project
Click to show the code
 [DependsOn(
...
    typeof(AbpBlobStoringModule)
    )]
public class firstappHttpApiModule : AbpModule
...
  • In the ItemGroup of rupbes.firstapp.HttpApi.Host.csproj add a reference onto Volo.Abp.BlobStoring.FileSystem-package.
Click to show the code
  <ItemGroup>
    <PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="9.1.0" />
    <PackageReference Include="Volo.Abp.Autofac" Version="9.1.0" />
    <PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="9.1.0" />
    <PackageReference Include="Volo.Abp.Swashbuckle" Version="9.1.0" />

    <PackageReference Include="Volo.Abp.BlobStoring.FileSystem" Version="9.1.0" />
  </ItemGroup>
  • Modify DependsOn-attribute of the firstappHttpApiHostModule-class of the rupbes.firstapp.HttpApi.Host.csproj-project
Click to show the code
 [DependsOn(
...
    typeof(AbpBlobStoringFileSystemModule)
    )]
public class firstappHttpApiHostModule : AbpModule
...
  • Modify ConfigureServices-method of the firstappHttpApiHostModule-class of the rupbes.firstapp.HttpApi.Host.csproj-project
Click to show the code
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        var configuration = context.Services.GetConfiguration();
        var hostingEnvironment = context.Services.GetHostingEnvironment();

        if (!configuration.GetValue<bool>("App:DisablePII"))
        {
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.LogCompleteSecurityArtifact = true;
        }

        if (!configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata"))
        {
            Configure<OpenIddictServerAspNetCoreOptions>(options =>
            {
                options.DisableTransportSecurityRequirement = true;
            });
            
            Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedProto;
            });
        }

        ConfigureAuthentication(context);
        ConfigureUrls(configuration);
        ConfigureBundles();
        ConfigureConventionalControllers();
        ConfigureHealthChecks(context);
        ConfigureSwagger(context, configuration);
        ConfigureVirtualFileSystem(context);
        ConfigureCors(context, configuration);

// start of the modification
        Configure<AbpBlobStoringOptions>(options =>
        {
            options.Containers.Configure("phbk-file-dto", container =>
            {
                container.IsMultiTenant = false; // or true
                container.UseFileSystem(fileSystem =>
                {
                    fileSystem.BasePath = "C:\\temp\\phbk-file-dto"; // or any folder you like or use something like this configuration["AbpBlobStoringOptions:PhbkFileDto"]
                });
            });
        });
// end of the modification

    }
Typescript Classes
Click to show the picture

project structure

  • UI Form properties is as follows:
Click to show the picture

project structure

Modify app-routing.module.ts-file as follows:

Click to show the code
const routes: Routes = [
...

/////////////////////////////////////////////////////////////////////////
{ path: 'PhbkFileDto/ViewPhbkFileDto/:hf2/:id2', canActivate:[AppGlblSettingsServiceCanActivateFn],
  loadChildren: () => import('./components/phbk-file-dto/phbk-file-dto-rv-lazy.routing.module').then(m => m.PhbkFileDtoRvLazyRoutingModule),
  data: {pm:'firstapp.PhbkFileDto', vn: 'PhbkFileDto', va: 'v', /* sf: true,  title: 'View File', */ hf: 'hf2',  id: 'id2', dp: 2}},

{ path: 'PhbkFileDto/AddPhbkFileDto/:hf2', canActivate:[AppGlblSettingsServiceCanActivateFn],
  loadChildren: () => import('./components/phbk-file-dto/phbk-file-dto-ra-lazy.routing.module').then(m => m.PhbkFileDtoRaLazyRoutingModule),
  data: {pm:'firstapp.PhbkFileDto.a', vn: 'PhbkFileDto', va: 'a', /* sf: true,  title: 'Add File', */ hf: 'hf2',  dp: 2}},

{ path: 'PhbkFileDto/DelPhbkFileDto/:hf2/:id2', canActivate:[AppGlblSettingsServiceCanActivateFn],
  loadChildren: () => import('./components/phbk-file-dto/phbk-file-dto-rd-lazy.routing.module').then(m => m.PhbkFileDtoRdLazyRoutingModule),
  data: {pm:'firstapp.PhbkFileDto.d', vn: 'PhbkFileDto', va: 'd', /* sf: true,  title: 'Delete File', */ hf: 'hf2',  id: 'id2',  dp: 2}},

{ path: 'PhbkFileDto', canActivate:[AppGlblSettingsServiceCanActivateFn], 
  loadChildren: () => import('./components/phbk-file-dto/phbk-file-dto-rl-lazy.routing.module').then(m => m.PhbkFileDtoRlLazyRoutingModule),
  data: {pm:'firstapp.PhbkFileDto', vn: 'PhbkFileDto', va: 'l', ms: true,  fh: 2, mh: 16, nh: 8, sf: true, /* title: 'Files', */  dp: 1, uid: 'c9daf6bddac646dfb568437fe280e49f' }  },
/////////////////////////////////////////////////////////////////////////
{ path: 'RDLPhbkFileDto', canActivate:[AppGlblSettingsServiceCanActivateFn],
  loadChildren: () => import('./components/phbk-file-dto/phbk-file-dto-rdl-lazy.routing.module').then(m => m.PhbkFileDtoRdlLazyRoutingModule),
  data: {pm:'firstapp.PhbkFileDto', vn: 'PhbkFileDto', va: 'l', ms: true, np: 'RDL', fh: 2, mh: 16, nh: 8, sf: true, /* title: 'Files', */  dp: 1, uid: 'ba198636ba014dbfa97d4cc7d0080265' }  },
];

Modify route.provider.ts-file as follows:

Click to show the code
import { RoutesService, eLayoutType } from '@abp/ng.core';
import { inject, provideAppInitializer } from '@angular/core';

export const APP_ROUTE_PROVIDER = [
  provideAppInitializer(() => {
    configureRoutes();
  }),
];

function configureRoutes() {
  const routes = inject(RoutesService);
  routes.add([
      {
        path: '/',
        name: '::Menu:Home',
        iconClass: 'fas fa-home',
        order: 1,
        layout: eLayoutType.application,
      },
      {
        path: '/RDLPhbkPhoneTypeDto',
        name: 'Phone Type Dlg',
        requiredPolicy: 'firstapp.PhbkPhoneTypeDto',
        iconClass: 'fas fa-phone',
        order: 20,
        layout: eLayoutType.application,
      },
      {
        path: '/PhbkPhoneTypeDto',
        name: 'Phone Type',
        requiredPolicy: 'firstapp.PhbkPhoneTypeDto',
        iconClass: 'fas fa-phone',
        order: 30,
        layout: eLayoutType.application,
      },

      {
        path: '/RDLPhbkFileDto',
        name: 'Phone book file Dlg',
        requiredPolicy: 'firstapp.PhbkFileDto',
        iconClass: 'fas fa-file',
        order: 40,
        layout: eLayoutType.application,
      },
      {
        path: '/PhbkFileDto',
        name: 'Phone book file',
        requiredPolicy: 'firstapp.PhbkFileDto',
        iconClass: 'fas fa-file',
        order: 50,
        layout: eLayoutType.application,
      }

  ]);
}
Result

After adding files you can download them

Click to show the picture

project structure

Or you can add the file

Click to show the picture

project structure

On the disk we have

Click to show the picture

project structure

⚠️ **GitHub.com Fallback** ⚠️