Adding files to an Angular ViewModel using DropzoneJS

I am facing a challenge in extracting file content and inserting it into a specific FileViewModel. This is necessary because I need to bundle all files with MainViewModel which contains a list of FileViewModel before sending it from the client (angular) to the server (.Net WebApi).

Does anyone have suggestions on how to approach this implementation?

Client ViewModels:

exprot class MainRequestViewModel{
  public FirstName: string;
  public LastName: string;
  public Comments: string;
  public FilesToUpload: Array<FileItemRequestViewModel>;
}

export class FileItemRequestViewModel{
  public FileContent: ArrayBuffer = null;
  public FileMimeType: string;
  public FileName: string;
  public NumberOfPagesInFile: number;
  public ItemPriority: number;
}

Answer №1

Here are a couple of recommendations:

1) For smaller files, such as images and attachments, consider sending them base64encoded over the wire while being mindful of payload limits defined in your webapi's web.config file.

In your entity model, include a property:

fileAsBase64: string

This allows you to convert a file from the dropzone component into a base64 string using the following method:

getBase64(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result);
      reader.onerror = (error) => reject(error);
});

On the C# side, define the file as a string and use it to convert the string back to a byte array:

 public class UploadedFileDto
    {
        public string Name { get; set; }
        public string FileAsBase64 { get; set; }

        [JsonIgnore]
        public string MimeType => Regex.Match(FileAsBase64, @"data:(?<type>.+?);base64,(?<data>.+)").Groups["type"].Value;

        [JsonIgnore]
        public byte[] Bytes =>
            Convert.FromBase64String(Regex.Match(FileAsBase64, @"data:(?<type>.+?);base64,(?<data>.+)").Groups["data"].Value);

    }

2) When dealing with larger files, consider sending the files in a separate call to the server and saving them temporarily. You will also need a function to clean these temporary files. Here is a controller snippet that includes size checks and only allows PDF files:

public async Task<HttpResponseMessage> Upload()
    {


        Dictionary<string, object> dict = new Dictionary<string, object>();
        try
        {

            var httpRequest = HttpContext.Current.Request;

            foreach (string file in httpRequest.Files)
            {

                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);

                var postedFile = httpRequest.Files[file];


                if (postedFile != null && postedFile.ContentLength > 0)
                {
                    int MaxContentLength = 1024 * 1024 * 50; //Size = 50 MB  

                    IList<string> AllowedFileExtensions = new List<string> { ".pdf" };
                    var ext = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf('.'));
                    var extension = ext.ToLower();
                    if (!AllowedFileExtensions.Contains(extension))
                    {

                        var message = string.Format("Please upload file of type .pdf");

                        dict.Add("error", message);
                        return await Task.FromResult(Request.CreateResponse(HttpStatusCode.BadRequest, dict));
                    }
                    else if (postedFile.ContentLength > MaxContentLength)
                    {

                        var message = string.Format("Please upload a file upto 50 mb.");

                        dict.Add("error", message);
                        return await Task.FromResult(Request.CreateResponse(HttpStatusCode.BadRequest, dict));
                    }
                    else
                    {
                        _fileService.SaveUploadedFile(postedFile);

                    }
                }

                var message1 = string.Format("File uploaded Successfully.");
                return await Task.FromResult(Request.CreateResponse(HttpStatusCode.OK, message1)); ;
            }
            var res = string.Format("Please upload a pdf.");
            dict.Add("error", res);
            return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
        }
        catch (Exception ex)
        {
            Log.Error(ex);
            var res = string.Format("Errors occured");
            dict.Add("error", res);
            return await Task.FromResult(Request.CreateResponse(HttpStatusCode.InternalServerError, dict));
        }
    }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transmitting a variety of content types in a single request

Is there a way to send multiple files along with extra JSON data to the API? I have noticed that the API is capable of handling various content types. I am wondering how I can create a header that includes two different content types: Multipart form data ...

Is there a way to manipulate data being passed to a subject.next() in RXJS before emitting it again?

I have a feeling that this question is going to reveal some gaps in my understanding of observables, but I'll ask it anyway. I want to create an RXJS subject that performs operations on the data before emitting it again. Let me explain with a simple ...

Eliminate duplicated partial objects within a nested array of objects in TypeScript/JavaScript

I'm dealing with a nested array of objects structured like this: const nestedArray = [ [{ id: 1 }, { id: 2 }, { id: 3 }], [{ id: 1 }, { id: 2 }], [{ id: 4 }, { id: 5 }, { id: 6 }], ] In the case where objects with id 1 and 2 are already grou ...

Utilizing useContext data in conjunction with properties

When using useContext in a component page, I am able to successfully retrieve data through useContext within a property. customColorContext.js import { createContext, useEffect, useState, useContext } from 'react'; // creating the context objec ...

Tips for refreshing a React component using incremental changes retrieved from an API

I am developing a unique React application using Next.js and TypeScript, with an api-backed data set in one component that needs to be cached indefinitely. Unlike traditional examples I have found online, my component must: Fetch only the most recent 100 ...

Problem Encountered with Inaccurate Binding of Dynamic Form Control Values in Angular

UPDATE: Follow this link to access the editor for my Stackblitz application, which demonstrates a simplified version of the issue regarding the "transfer" of value between the first and second controls. I am currently developing a dynamic form in Angular ...

What steps can be taken to eliminate the 404 error when refreshing an Angular 8 Single Page Application (SPA) without using

In my single page application project, I am utilizing Angular 8. Upon uploading my published code to the IIS server without using hash(#) in routing, I encounter a 404 error when attempting to refresh the page. Can anyone provide assistance on how to res ...

In Vue using Typescript, how would I go about defining a local data property that utilizes a prop as its initial value?

When passing a prop to a child component in Vue, the documentation states: The parent component updates will refresh all props in the child component with the latest value. Avoid mutating a prop inside a child component as Vue will warn you in the consol ...

Exploring the power of TypeScript for authenticating sessions with NextJS

Utilizing next-auth's getSession function in API routes looks something like this for me: const mySession = await getSession({ req }); I have confirmed that the type of the mySession is outlined as follows: type SessionType = { user: { email: s ...

Tips for creating a custom hook that is type safe:

When I use the custom function createUser, I've noticed that I can pass numbers instead of strings without receiving an error. Surprisingly, even if I forget to include an argument, no red squiggles appear. const [userState, createUser] = useCre ...

What could be causing the global npm package to not be utilized for module dependencies?

My typescript and ts-node are already installed globally. In my package.json file, I have the necessary configurations to run tests with npm test. Everything works fine since ts-node and typescript are installed as local modules. { "name": "two_sum", ...

Ways to retrieve the property of an object within a view while being sourced from an observable

I am currently working with the following provider code: getWorldCities2() { return this.http.get('../assets/city.list.json') .map(res => res.json()); } Within my TypeScript code, I have implemented the following: ionViewDidLoad() { ...

Angular Universal: Troubleshooting an Unrendered Route

Struggling for hours to make my site Universal and support Server Side Rendering, I came across the issue where the base route '' is not being rendered by the server. Surprisingly, all other routes are functioning properly when directly called fr ...

Automatic verification of OTP in Ionic 3

Seeking assistance for implementing auto OTP verification in a project I am working on. After the user enters their phone number, I have come across some examples for Ionic 1 with Angular 1 online. However, I am specifically looking for examples using Io ...

Is it possible that using npm link could be the root cause of the "module not

As I delve into understanding how to utilize TypeScript modules in plain JavaScript projects, it appears that I am facing a limitation when it comes to using npm linked modules. Specifically, I can successfully use a module that is npm-linked, such as &apo ...

Can someone explain why the Next 13 API route is showing up as empty?

I am currently working with Next 13 and I am attempting to create a simple API route. My goal is to have a: "hi" returned when I visit localhost:3000/api/auth. Despite not encountering a 404 error or any errors in the terminal or console, I can&a ...

Dealing with challenges in integrating ngx-masonry with Angular 14

I am currently working with Angular 14 framework and the ngx-masonry library (https://www.npmjs.com/package/ngx-masonry/v/14.0.1). However, I am facing some issues where it is not functioning correctly. I would appreciate any assistance or guidance on how ...

I'm struggling to include a link in my project card component - I've tried using both the Link tag and anchor tag, but so far, I haven't been successful in

I am having trouble getting the link tag to work properly in my UI. I have tried using both the link and anchor tags, but neither seems to be functioning as expected. Can someone please advise on how to fix this issue? I was expecting the link tag to prop ...

Include a class in ul > li elements upon page load in Angular4

I attempted to add a class to each "li" element in an Angular4 page, but the class was not applied. Here is the relevant HTML code: <ul class="pagination"> <button class="previous" (click)="previous()">Previous</button> <button ...

Utilizing several data sources within a single mat-table

Hello, I require assistance with a task. I am trying to display multiple mat-tables with different data sources in my component.ts file Groups(){ this.apiSvc.Cards().subscribe((rsp: any) => { this.groups = rsp; this ...