411 File upload and download of ABP framework applications - chempkovsky/CS82ANGULAR GitHub Wiki
- 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 onlyadd
anddelete
methods are implemented.
- In the
Phbk
folder of therupbes.firstapp.Domain.csproj
project, create a class as shown below. We have composite primary key which inludesFlNm
.
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 };
}
}
}
- Repeat the steps of the 403 Modify DBContext for the first entity (PhoneType).
OnModelCreating
must be as follows:
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 });
});
}
}
- Repeat the steps of the 404 First View (PhoneType). Wizard repository
Click to show the picture
- Repeat the steps of the 405 First Web Api Service (PhoneType)
Click to show the picture
- 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
ofrupbes.firstapp.HttpApi.csproj
-project add a reference ontoVolo.Abp.BlobStoring
-package. In our case it isVersion="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 thefirstappHttpApiModule
-class of therupbes.firstapp.HttpApi.csproj
-project
Click to show the code
[DependsOn(
...
typeof(AbpBlobStoringModule)
)]
public class firstappHttpApiModule : AbpModule
...
- In the
ItemGroup
ofrupbes.firstapp.HttpApi.Host.csproj
add a reference ontoVolo.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 thefirstappHttpApiHostModule
-class of therupbes.firstapp.HttpApi.Host.csproj
-project
Click to show the code
[DependsOn(
...
typeof(AbpBlobStoringFileSystemModule)
)]
public class firstappHttpApiHostModule : AbpModule
...
- Modify
ConfigureServices
-method of thefirstappHttpApiHostModule
-class of therupbes.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
}
-
Repeat the steps of the 408 Typescript Classes for the First View of ABP framework.
-
Repeat the steps of the 409 Navigation aware typescript components for the First View of ABP framework.
-
UI List properties is as follows:
Click to show the picture
- UI Form properties is as follows:
Click to show the picture
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,
}
]);
}
After adding files you can download them
Click to show the picture
Or you can add the file
Click to show the picture
On the disk we have