Getting the File object from b-form file into sql database

Hello,

I’m building a simple CR (no updating or deleting) API and an accompanying webform for permit applications and wanted to include the ability to upload a document along with the submission. I created the small API from following the Microsoft Docs and created a vue.js frontend form that works pretty well- except for getting the file to get stored into the backend table. Using the documentation from the bootstrap docs I was able to get the files name, size, and type, but can’t seem to get the document play nice and get into the table.

In the sql table, the field is set to varbinary(max). In my API I am using byte[] for the mapped property.

Using Entity Framework 6,
public byte[] Drawing { get; set; } entity.Property(e => e.Drawing);

I’ve played around a little with the headers, (using axios) and currently I have

'content-type': 'application/json; charset=utf-8'

or nothing, both seem to be ok- it is inserting all of the other data. I also have

allow: 'multipart/form-data'

in the index.js file for the route.

I have tried converting the incoming file to bytes/ byteArrays, Uint8Array, blobs, etc but it is not getting into the POST request according to the Network traffic in the browser. I’ve tried a few conversions, This one being the last attempt:

this.model.Drawing = this.convertToByte(this.drawing);

convertToByte(doc) {
           if (doc) {
               console.log(doc.name)
               var blob = new Blob([doc]),
               fileReader = new FileReader(),
               array;

               fileReader.onload = function () {
                   array = this.result;
                   console.log("Array contains", array.byteLength, "bytes.");
               };

               var converted = fileReader.readAsArrayBuffer(blob);

               return converted;
                }
                else {
                return null;
                }```


This seems like something that would be common/ obvious/ standard procedure and I just need some ideas.

What do I need to do to the File object for it to be inserted into the SQL table?  Is storing it into a SQL DB something that is done, or do people save that uploaded doc into a folder on the server?

Thank you for your time and help-
J

Google just decided to return some more relevant examples using IFormFile type so I’ll give that a try and see where it goes.

I got it figured out and thought I’d share the resulting code setup. The key for me was creating a new FormData object and appending the Files to it.

The SQL table field type:
Drawing varbinary(max)

My model: (I’m using the EF6 context and it threw a fit for the IFormFiles not mapping)

public class Permit {
        ...Other fields...
        public string DrawingName { get; set; }
        [NotMapped]
        public IFormFile inputDrawing { get; set; }
        public byte[] Drawing { get; set; }
        public string Comments { get; set; }
}

My controller:


        [HttpPost]
        public async Task<ActionResult> Post([FromForm]Permit indata)
        {
            if (ModelState.IsValid)
            {
                try
                {
                     //  Convert the IFormFile into bytes in order to be stored in the sql table
                    await Task.Run(() =>
                    {
                        IFormFile drawing = indata.inputDrawing;
                        if (drawing != null)
                        {
                            byte[] dbytes = null;
                            using (var fs1 = drawing.OpenReadStream())
                            using (var ms1 = new MemoryStream())
                            {
                                fs1.CopyTo(ms1);
                                dbytes = ms1.ToArray();
                            }
                            indata.Drawing = dbytes;
                        }
                    });
                   
                    // Submit the incoming Permit to the database
                    var postId = await dbcontext.Permit.AddAsync(indata);
                    if (postId > 0)
                    {
                        return Ok(postId);
                    }
                    else
                    {
                        return NotFound("An error occurred with the API and submitting data into the database");
                    }
                }
                catch (Exception ex)
                {
                    return BadRequest(ex);
                }
            }
            return BadRequest();
        }

My axios api service in its own js file (from the CRUD application tutorial by okta):

import axios from 'axios'

const client = axios.create({
    baseURL: 'https://localhost:44367/septicpermits',
    json: true
})

export default {
    create(data) {
        console.log("create hit. submitting to api")
        var result = this.execute('Post', '/', data)
        return result;
    },
async execute(method, resource, data) {
        console.log("executing to client")
        return client({
            method,
            url:
            resource,
            data,
            headers: { 'content-type': "multipart/form-data; boundary=${data._boundary}" }
        })
            .then(req => { return req.data })
            .catch(error => console.log(error))
    }
}

In my Vue: (Don’t know if that enctype is needed, but will test without it to see what it does at a later time)

<template>
<b-form id="permitform" name="permitform" @submit.prevent="InsertPermit(model)" method="post" enctype="multipart/form-data">
<lots of b-form elements tied to the model properties with v-model="model.inputDrawing">
</template>
<script>
    import api from '@/PermitApplicationApiService';

    export default {
        data() {
            return {
                loading: false,
                records: [],
                form: {},
                model: {},
                async InsertPermit() {
                let formelements = document.querySelector('form');
                let formdata = new FormData(formelements);

                if (this.model.inputDrawing) {
                    console.log("drawing appended");
                    formdata.append("inputDrawing", this.model.inputDrawing);
                }

                await api.create(formdata)
                    .then(response => {
                        console.log('Awesome, it submitted')
                        this.$alert('Your application submitted successfully.  A Technician will review the submitted data and contact you shortly.');
                    })
                    .catch(err => {
                        console.log(err);
                        this.$alert('Code 404. Your application submitted successfully');
                    });
            },

Not sure if there is a better way, or if some things are not needed, but this worked for me for now so I’ll continue with it until I get more experience and can update it.