1

enter image description hereThis is my model class

public class ImageModel
{
    [Key]
    public int ImageId { get; set; }

    [Column(TypeName = "nvarchar(50)")]
    public string Title { get; set; }

    [Column(TypeName = "nvarchar(100)")]
    [DisplayName("Image Name")]
    public string ImageName { get; set; }

    [NotMapped]
    [DisplayName("Upload File")]
    public IFormFile ImageFile { get; set; }


}

This is my controller class for post request And I create a wwwroot folder to save Image

[Route("api/[Controller]")]
[ApiController]
public class ImageController : Controller
{
    private readonly Databasecontext _context;
    private readonly IWebHostEnvironment _hostEnvironment;



    

    public ImageController(Databasecontext context, IWebHostEnvironment hostEnvironment)
    {
        _context = context;
        this._hostEnvironment = hostEnvironment;
    }

    // GET: Image
    public async Task<IActionResult> Index()
    {
        return View(await _context.Images.ToListAsync());
    }

    // GET: Image/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: Image/Create

    [HttpPost]
    
    public async Task<IActionResult> Create([Bind("ImageId,Title,ImageName")] ImageModel imageModel)
    {
        if (ModelState.IsValid)
        {
            //Save image to wwwroot/image
            string wwwRootPath = _hostEnvironment.WebRootPath;
            string fileName = Path.GetFileNameWithoutExtension(imageModel.ImageFile.FileName);
            string extension = Path.GetExtension(imageModel.ImageFile.FileName);
            imageModel.ImageName = fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension;
            string path = Path.Combine(wwwRootPath + "/Image/", fileName);
            using (var fileStream = new FileStream(path, FileMode.Create))
            {
                await imageModel.ImageFile.CopyToAsync(fileStream);
            }
            //Insert record
            _context.Add(imageModel);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(imageModel);


    }

This is my DB context

 public DbSet<ImageModel> Images { get; set; }

I just need to test this using postman and combine it with angular. Can someone help me? when I send an image through postman I get this error The request entity has a media type that doesn't support server or resource does not support.

4
  • Hi @scorpion private, could you please share how do you post the data in Postman? I cannot reproduce the issue and post the data to action successfully. Commented Oct 8, 2021 at 8:51
  • I have added the output of the postman above Commented Oct 8, 2021 at 16:36
  • I perform that functionality by sending a base64 and the file name, when the API receives the base64 it converts it to an IFormFile and copies it to a predefined directory Commented Oct 8, 2021 at 18:27
  • Can you give me the sample code @Juan_H Commented Oct 9, 2021 at 2:37

2 Answers 2

0

That is because you use [ApiController] in your controller, it allows data from body by default. So you need specific the source by using [FromForm] attribute like below:

[HttpPost]
public async Task<IActionResult> Create([Bind("ImageId,Title,ImageName")][FromForm] ImageModel imageModel)
{
    //..
    return View(imageModel);
}

Besides, if you use [Bind("ImageId,Title,ImageName")], ImageFile cannot be binded to the model.

Sign up to request clarification or add additional context in comments.

Comments

0

Sorry for my Spanish in the code.

This is how i upload the file in Base64 and then copy the file to a Directory. I Pupulate the Object ArchivoAnexoUploadDto using a page http://base64.guru/converter/encode/file for convert a file to a base64.

I Hope tha this extract of the code will be usefull for you

1 - Controller

[HttpPost("UploadFileList")]
    public async Task<IActionResult> UploadFileList(List<ArchivoAnexoUploadDto> fileList)
    {
        IOperationResult<object> operationResult = null;
        try
        {
            operationResult = await _fileService.UploadFileList(fileList);

            if (!operationResult.Success)
            {
                return BadRequest(operationResult.ErrorMessage);
            }

            return Ok(operationResult.Entity);

        }
        catch (Exception ex)
        {
            return BadRequest(operationResult.Entity);
        }

    }

I Recibe a List of Objects < ArchivoAnexoUploadDto > and the service converts the base 64 to Bytes array.

2 - Service

public async Task<IOperationResult<object>> UploadFileList(List<ArchivoAnexoUploadDto> files)
    {
        List<ArchivoAnexoCreateDto> fileList = PrepareFileList(files);

        Response result = ValidateFiles(fileList);

        if (!result.Status)
        {
            Response responseError = new()
            {
                Status = false,
                Message = ((FormFile)result.Object).FileName,
                MessageDetail = result.Message
            };
            return OperationResult<object>.Ok(responseError);
        }

        var saveResult = await SaveFileList(fileList);

        Response respuesta = new()
        {
            Status = true,
            Message = "Los archivos fueron almacenados exitosamente.",
            MessageDetail = ""
        };
        return OperationResult<object>.Ok(respuesta);
    }


    private List<ArchivoAnexoCreateDto> PrepareFileList(List<ArchivoAnexoUploadDto> files)
    {
        List<ArchivoAnexoCreateDto> formFileList = new List<ArchivoAnexoCreateDto>();

        foreach (ArchivoAnexoUploadDto newFile in files)
        {

            byte[] fileBytes = Convert.FromBase64String(newFile.Base64);

            string filePath = Path.Combine(_fileSettings.PrincipalPath, _fileSettings.PrincipalFolderName, newFile.NombreArchivo);
            MemoryStream memoryStream = new MemoryStream();
            memoryStream.Write(fileBytes, 0, fileBytes.Length);

            FormFile fileData = new FormFile(memoryStream, 0, memoryStream.Length, newFile.NombreArchivo, newFile.NombreArchivo);

            ArchivoAnexoCreateDto fileDto = new()
            {
                FileId = 0,
                Data = fileData,
                FileName = newFile.NombreArchivo,
                Module = newFile.Modulo
            };
            formFileList.Add(fileDto);
        }

        return formFileList;
    }

    private Response ValidateFiles(List<ArchivoAnexoCreateDto> fileList)
    {
        foreach (ArchivoAnexoCreateDto fileObj in fileList)
        {
            IFormFile file = fileObj.Data;
            try
            {
                ValidateFile(file);
            }
            catch (Exception exception)
            {
                return new Response { Status = false, Message = exception.Message, Object = file };
            }
        }
        return new Response { Status = true, Message = "" };
    }

The Service recibe the Array and PrepareFileList return the same data but the array have IFormFile instead of Base64 string.

3 - Dtos

public sealed class ArchivoAnexoUploadDto
{
    public long AnexoFileId { get; set; }
    public string Base64 { get; set; }
    public string NombreArchivo { get; set; }
    public Module Modulo {get; set;}
}

public sealed class ArchivoAnexoCreateDto
{
    public long FileId { get; set; }
    public IFormFile Data { get; set; }
    public int FileTypeId { get; set; }
    public string FileName { get; set; }
    public Module Module { get; set; }
}

ArchivoAnexoUploadDto Is the Dto that recives the base64 and the name of the file.

ArchivoAnexoCreateDto Is the Dto with IFormFile property and is used to copy the file to a Directory.

4 - Validate IFormFile To Copy to Dir

private void ValidateFile(IFormFile fileToCreate)
    {
        if (fileToCreate == null)
        {
            throw new Exception("No ha enviado ningun archivo.");
        }

        IOperationResult<string> fileExtensionResult = _fileService.GetFileExtension(fileToCreate);

        if (!fileExtensionResult.Success)
        {
            throw new Exception(fileExtensionResult.ErrorMessage);
        }

        if (!_fileSettings.AllowedExtensions.Contains(fileExtensionResult.Entity))
        {
            throw new Exception("La extención del archivo no es permitida.");
        }

        IOperationResult<long> fileSizeResult = _fileService.GetFileSize(fileToCreate);

        if (!fileSizeResult.Success)
        {
            throw new Exception("Ha ocurrido un error obteniendo el tamaño del archivo.");
        }

        if (fileSizeResult.Entity > _fileSettings.MaxFileSize)
        {
            throw new Exception("El tamaño del archivo supera el limite.");
        }
    }

This are Conditions for validate (Only for explain) I Did this stuff because the business configured a list of extensions, a size limit of the files, etc.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.