Published on

Add profile picture to User Entity in ABP app using BlobStore and Minio. Part 6

2 min read
Table of Contents

Intro

In this post we will implement the profile picture upload for the ABP app using BlobStore and Minio.

Create a new project

abp new ProfilePictureSample

Create a container

Create the container in Domain project.

Install Volo.Abp.BlobStoring NuGet package to your Domain project

[BlobContainerName("profile-picture")]
public class ProfilePictureContainer
{
}

Configure Minio

Install Volo.Abp.BlobStoring.Minio NuGet package to your Web and add [DependsOn(typeof(AbpBlobStoringMinioModule))] to the Web Module

Configuration is done in the ConfigureServices method of your module class

Configure<AbpBlobStoringOptions>(options =>
{
    options.Containers.ConfigureDefault(container =>
    {
        container.UseMinio(minio =>
        {
            minio.EndPoint = "localhost:9900"; // your minio endPoint
            minio.AccessKey = "AKIAIOSFODNN7EXAMPLE"; // your minio accessKey
            minio.SecretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"; // your minio secretKey
            minio.BucketName = "profile-picture"; // your minio bucketName
        });
    });
});

Extend User Entity

Configure extra properties

Create the Constant file in the Domain.Shared project.

public static class ProfilePictureConsts
{
    public const string ProfilePictureId = "ProfilePictureId";
}

In the Domain.Shared project update the ProfilePictureSampleModuleExtensionConfigurator file inside the ConfigureExtraProperties methods with the following.

ObjectExtensionManager.Instance.Modules()
    .ConfigureIdentity(identity =>
    {
        identity.ConfigureUser(user =>
        {
            user.AddOrUpdateProperty<Guid>(ProfilePictureConsts.ProfilePictureId);
        });
    });

Configure ef core

In the EntityFrameworkCore project update the ProfilePictureSampleEfCoreEntityExtensionMappings file inside the Configure method. Update the OneTimeRunner.Run with the following

ObjectExtensionManager.Instance
    .MapEfCoreProperty<IdentityUser, Guid>(ProfilePictureConsts.ProfilePictureId);

Add Migrations

Navigate to the EntityFrameworkCore.

cd .\src\ProfilePictureSample.EntityFrameworkCore\

Add migrations

dotnet ef migrations add "update_user"

Apply the migrations

dotnet ef database update

Create the AppService

Create a AppService to upload and view the profile picture.

[Authorize]
public class ProfilePictureAppService : ProfilePictureSampleAppService
{
    private readonly IBlobContainer<ProfilePictureContainer> _blobContainer;
    private readonly IRepository<IdentityUser, Guid> _repository;

    public ProfilePictureAppService(IBlobContainer<ProfilePictureContainer> blobContainer, IRepository<IdentityUser, Guid> repository)
    {
        _blobContainer = blobContainer;
        _repository = repository;
    }

    public virtual async Task<Guid> UploadAsync(IFormFile file)
    {
        await using var memoryStream = new MemoryStream();
        await file.CopyToAsync(memoryStream).ConfigureAwait(false);
        if (CurrentUser.Id == null)
        {
            return Guid.Empty;
        }

        var user = await _repository.GetAsync(CurrentUser.Id.Value).ConfigureAwait(false);
        var pictureId = user.GetProperty<Guid>(ProfilePictureConsts.ProfilePictureId);

        if (pictureId == Guid.Empty)
        {
            pictureId = Guid.NewGuid();
        }
        var id = pictureId.ToString();
        if (await _blobContainer.ExistsAsync(id).ConfigureAwait(false))
        {
            await _blobContainer.DeleteAsync(id).ConfigureAwait(false);
        }
        await _blobContainer.SaveAsync(id, memoryStream.ToArray()).ConfigureAwait(false);
        user.SetProperty(ProfilePictureConsts.ProfilePictureId, pictureId);
        await _repository.UpdateAsync(user).ConfigureAwait(false);
        return pictureId;
    }

    public async Task<FileResult> GetAsync()
    {
        if (CurrentUser.Id == null)
        {
            throw new FileNotFoundException();
        }

        var user = await _repository.GetAsync(CurrentUser.Id.Value).ConfigureAwait(false);
        var pictureId = user.GetProperty<Guid>(ProfilePictureConsts.ProfilePictureId);
        if (pictureId == default)
        {
            throw new FileNotFoundException();
        }

        var profilePicture = await _blobContainer.GetAllBytesOrNullAsync(pictureId.ToString()).ConfigureAwait(false);
        return new FileContentResult(profilePicture, "image/jpeg");

    }
}