This forum is not used anymore. Please ask new questions to Stack Overflow: https://stackoverflow.com/questions/tag ... ort=newest (use aspnetboilerplate tag).
By zokho
#5648 Hi,
Does anyone know that if its feasible to upload files using Dtos in the Application layer? If yes, can I have a sample code which shows how to define properties in DTO classes and how to call the service from AngularJS?

Thanks,
By Paddyfink
#5663 Hello,

I've implemented something like that to send email with attachment. this is my DTO :

Code: Select all public class AttachmentDto : EntityDto<long>
    {
        public string Name { get; set; }
        public string Content { get; set; }
        public string ContentType { get; set; }
        public int ContentLength { get; set; }
    }


But in order to convert my file into string, I've created a controller that receive the file, convert it into string and send the string back. Then I call my application service with the string. The controller looks like this :

Code: Select allpublic async virtual Task<JsonResult> AddAttachment()
        {
            try
            {
                //Check input
                if (Request.Files.Count <= 0 || Request.Files[0] == null)
                {
                    throw new UserFriendlyException(L("ProfilePicture_Change_Error"));
                }

                var file = Request.Files[0];

                // todo : put the limit in the settings
                if (file.ContentLength > 5242880) //Mg.
                {
                    throw new UserFriendlyException(L("EmailAttachmentSizeLimit"));
                }

                MemoryStream target = new MemoryStream();
                file.InputStream.CopyTo(target);
                byte[] data = target.ToArray();
                string base64String = System.Convert.ToBase64String(data, 0, data.Length);

                //Return success
                return Json(new MvcAjaxResponse(new AttachmentModel
                {
                    Content = base64String,
                    ContentType=file.ContentType,
                    Name=file.FileName,
                    ContentLength=file.ContentLength
                }));
            }
            catch (UserFriendlyException ex)
            {
                //Return error message
                return Json(new MvcAjaxResponse(new ErrorInfo(ex.Message)));
            }
        }


I
By zokho
#5829 Hi
Thanks for your solution and sorry for the late response. Actually, I have replied but not sure where it has gone!
I have got 2 questions followed by a request regarding your approach:
1) When you say a Controller, do you mean an API within the Api project or a normal Controller and an action defined in the Web project?
2) Why are you converting the uploaded file to String?! Do you save the converted string in DB or store in a folder?
3) Could you please send the Angular code you use to call the Controller and the service?

Thanks
By GuillaumeMorin
#5856 We had to create a ApiController that receive the file and store it into a database table FileUpload. Then the newly created record id is returned to client.
We plan to change this architecture so the file is stored somewhere else than the database, like Azure Storage.

Code: Select allusing System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Abp.Utils.Extensions;
using Nito.AsyncEx.Synchronous;
using PMP.FileUpload.Command.Remove;
using PMP.FileUpload.Command.Upload;

namespace PMP.Web.Controllers
{
    public class FileUploadController : ApiController
    {
        private readonly IUploadService _uploadService;
       
        public FileUploadController(
            IUploadService uploadService)
        {
            _uploadService = uploadService;
        }

        /// <summary>
        ///
        /// </summary>
        /// <returns>Return the list of fileId uploaded</returns>
        [HttpPost]
        public async Task<List<int>> Upload()
        {
            var output = new List<int>();
           
            // Check if the request contains multipart/form-data.
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

            var streamContent = GetStreamContent();
            var streamProvider = await streamContent.ReadAsMultipartAsync();

            foreach (var item in streamProvider.Contents)
            {
                if (item.Headers.ContentDisposition.Name.Contains("file"))
                {
                    var fileName = item.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
                    var bytes = item.ReadAsByteArrayAsync().WaitAndUnwrapException();

                    // With IE, filename is a fullpath, so we take just the filename
                    fileName = Path.GetFileName(fileName);

                    var uploadOutput = _uploadService.Execute(new UploadInput()
                    {
                        FileBytes = bytes,
                        FileName = fileName
                    });

                    output.Add(uploadOutput.FileId);
                }
            }

            return output;
        }

        /// <summary>
        /// ReadAsMultipartAsync() throws an exception if we do not do this. It adds a \r\n at the end of the stream.
        /// See http://stackoverflow.com/a/27050229
        /// </summary>
        /// <returns>StreamContent</returns>
        private StreamContent GetStreamContent()
        {
            Stream reqStream = Request.Content.ReadAsStreamAsync().WaitAndUnwrapException();
            MemoryStream tempStream = new MemoryStream();
            reqStream.CopyTo(tempStream);

            tempStream.Seek(0, SeekOrigin.End);
            StreamWriter writer = new StreamWriter(tempStream);
            writer.WriteLine();
            writer.Flush();
            tempStream.Position = 0;


            StreamContent streamContent = new StreamContent(tempStream);
            foreach (var header in Request.Content.Headers)
            {
                streamContent.Headers.Add(header.Key, header.Value);
            }
            return streamContent;
        }

       
    }

   
}
By Sergii
#13793 Hi, the proposed approach implies two submits to server:
1) submit file only;
2) dto with file id;

Is it correct ? Then how about validation or other erors on second step, we have a risk to loose related file data.
Maybe someone can propose other approach with single submit and server side data validation like it works for DTO's ?
By gpcaretti
#19957
zokho wrote:Hi,
Does anyone know that if its feasible to upload files using Dtos in the Application layer? If yes, can I have a sample code which shows how to define properties in DTO classes and how to call the service from AngularJS?


This is the same issue I have!

I really don't know where to start. Does anybody have a working example with ABP, AngularJs page and an Application Service or an AbpApiController?

Please, help!
Gp
By juslwk
#20152 Hi, I am creating a file storage system using .net core, here is a working example which u can test with postman
this is my api controller
Code: Select allpublic async Task<EntityDto> UploadFile([FromForm] UploadFileInput input)
        {
            File file = ObjectMapper.Map<File>(input);
            Stream stream = input.File.OpenReadStream();
            var id = await _fileManager.UploadFileToAzure(file, stream, AbpSession.GetUserId());

            return new EntityDto() { Id = id };

        }


this is my DTO
Code: Select all[AutoMapTo(typeof(File))]
    public class UploadFileInput
    {
        public string Description { get; set; }
        public int ParentFolderID { get; set; }

        [Required]
        public IFormFile File { get; set; }

    }


this is my file entity
Code: Select all[Table("Files")]
    public class File : FullAuditedEntity, IOpenedAudited
    {
        public const int MaxNameLength = 256;
        public const int MaxDescriptionLength = 64 * 1024; //64KB

        [ForeignKey("UserId")]
        public User User { get; set; }
        public long UserId { get; set; }

        [Required]
        [MaxLength(MaxNameLength)]
        public virtual string Name { get; set; }

        [MaxLength(MaxDescriptionLength)]
        public virtual string Description { get; set; }

        public virtual long Length { get; set; }
        public virtual string ContentType { get; set; }
        public virtual string Extension { get; set; }

        public virtual string Uri { get; set; }
        public virtual string StoredFileName { get; set; }

        [ForeignKey("ParentFolderId")]
        public Folder ParentFolder { get; set; }
        public int? ParentFolderId { get; set; }

        public byte PublicPermissionLevel { get; set; }

        [ForeignKey("OwnerUserId")]
        public User OwnerUser { get; set; }
        public long OwnerUserId { get; set; }

        public long? LastOpenedUserId { get; set; }
        public DateTime? LastOpenedTime { get; set; }
        public bool IsTrashed { get; set; }

        public virtual ICollection<FilePermission> FilePermissions { get; set; }

        protected File()
        {
            IsTrashed = false;
            PublicPermissionLevel = (byte)PermissionLevel.None;
            this.FilePermissions = new HashSet<FilePermission>();
        }

    }


i do custom mapping to map my file dto to my file entity
Code: Select allConfiguration.Modules.AbpAutoMapper().Configurators.Add(config =>
            {
                config.CreateMap<UploadFileInput, File>()
                .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.File.FileName))
                .ForMember(dest => dest.ContentType, opt => opt.MapFrom(src => src.File.ContentType))
                .ForMember(dest => dest.Length, opt => opt.MapFrom(src => src.File.Length));

            });


and this is test with postman
I put the authorization bearer token into my header, in my body i post using form data,
Key Type Value
File File Choose your file here
Description Text Test Description
ParentFolderID Text 1

finally send a post request to your url eg. http://localhost:21021/api/services/app ... UploadFile