How to Upload Files to Mega Cloud Storage Using C# & .NET Core

Introduction

Introducing a game-changer in cloud integration: Mega Cloud meets .NET Core 8.0! Say goodbye to file upload woes and hello to seamless, secure, and scalable solutions. In this guide, we'll navigate the fusion of Mega Cloud's power with the versatility of .NET Core 8.0, empowering you to revolutionize your file management system. Whether you're a seasoned developer or just diving in, get ready for practical insights, code snippets, and a transformative journey. Join us as we unlock the potential of Mega Cloud and elevate your applications to new heights. Let's make file uploads a breeze together!

Mega

Step 1. Sign Up for Mega Cloud Account

Begin by signing up for a Mega Cloud account if you haven't already. Navigate to the Mega Cloud website and follow the registration process to create your account. Once done, you'll have access to your Mega Cloud dashboard.

Step 2. Install Mega SDK for .NET Core

Next, install the Mega API Client SDK for .NET Core in your project. You can do this via the NuGet package manager or by manually adding the SDK reference to your project.

You can also do this by running the following command in the Package Manager Console:

Install-Package MegaApiClient

Mega API Client

Step 3. Integrate File Upload and Image Retrieval into Category Page Logic

Now that we have our backend methods for uploading files to Mega Cloud and retrieving images from Mega, let's integrate these functionalities into our category page HTML. We'll modify the HTML structure to include elements for handling file upload and displaying images. Follow these steps to seamlessly incorporate file upload and image display functionalities into your category page:

!-- Acknowledgment Modal -->
<div class="modal" id="aknoModal" data-backdrop="static" data-keyboard="false">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <!-- Modal Header -->
            <div class="modal-header">
                <h6 class="modal-title">
                    Create Product Category
                </h6>
                <button type="button" class="close" data-dismiss="modal">
                    ×
                </button>
            </div>
            <!-- Modal body -->
            <div class="modal-body multi-control-form">
                <div class="card">
                    <div class="card-body">
                        <div class="row">
                            <div class="col-md-6">
                                <div class="form-group">
                                    <label>Name <span class="text-danger">*</span></label>
                                    <input id="txtCatName" type="text" class="form-control">
                                </div>
                            </div>
                            <div class="col-md-6">
                                <div class="form-group">
                                    <label>Group <span class="text-danger">*</span></label>
                                    <select id="ddlCatGroup" class="form-control">
                                        <option value="0">--Select--</option>
                                        <option value="1">Group-1</option>
                                        <option value="2">Group-2</option>
                                    </select>
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-md-12">
                                <div class="form-group">
                                    <label>Description<span class="text-danger">*</span></label>
                                    <textarea id="txtCatDesc" class="form-control"></textarea>
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-md-6">
                                <div class="form-group">
                                    <label>Image <span class="text-danger">*</span></label>
                                    <input id="fuImage" type="file" class="form-control" accept=".jpg,.jpeg,.png,.gif,.svg" required>
                                    <span style="color:#f00;">(.jpg, .gpeg, .png, .gif, .svg)</span>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <div class="form-group">
                                    <label>Status <span class="text-danger">*</span></label>
                                    <select id="ddlStatus" class="form-control">
                                        <option value="Y">Enabled</option>
                                        <option value="N">Disabled</option>
                                    </select>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Modal footer -->
            <div class="modal-footer">
                <button id="btnSave" type="button" class="btn btn-primary btnsend">
                    <i class="icon-send1"></i> Save
                </button>
                <button type="button" class="btn btn-danger BtnReset" data-dismiss="modal">
                    <i class="icon-x1"></i> Cancel
                </button>
            </div>
        </div>
    </div>
</div>

Create an HTML Table like below for data bind.

<div class="section-body">
    <button class="btn btn-primary" id="add-new-cat"><i class="fas fa-plus"></i> Add New</button>
    <div class="row mt-4">
        <div class="col">
            <div class="card">
                <div class="card-body">
                    <div class="table-responsive table-invoice">
                        <table class="table table-striped table-bordered" id="CategoryTable">
                            <thead>
                                <tr>
                                    <th>SN</th>
                                    <th>Name</th>
                                    <th>Group</th>
                                    <th>Description</th>
                                    <th>Image</th>
                                    <th>Status</th>
                                    <th>Action</th>
                                </tr>
                            </thead>
                            <tbody>
                                 
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Step 4. Integrate Swal2 to show different types of message

With  Swal2 integrated, you can now customize the appearance and behavior of messages according to different scenarios, providing users with clear and intuitive feedback. Please find the Installation script below.

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

Step 5.  Write the Css for Spinner or Loader when the data is fetched from DB


/* CSS for the loading spinner animation */
.lds-ring {
    display: inline-block;
    position: relative;
    width: 64px;
    height: 64px;
}

    .lds-ring div {
        box-sizing: border-box;
        display: block;
        position: absolute;
        width: 51px;
        height: 51px;
        margin: 6px;
        border: 6px solid #3498db;
        border-radius: 50%;
        animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
        border-color: #3498db transparent transparent transparent;
    }

        .lds-ring div:nth-child(1) {
            animation-delay: -0.45s;
        }

        .lds-ring div:nth-child(2) {
            animation-delay: -0.3s;
        }

        .lds-ring div:nth-child(3) {
            animation-delay: -0.15s;
        }

@keyframes lds-ring {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

Step 6. Write the below JS code for Data Save and retrieve

<script type="text/javascript">
    $(document).ready(function () {
        $('#CategoryTable').DataTable();
        fetchData();
    });



    function fetchData() {
        // Show loading spinner
        Swal.fire({
            title: 'Please wait...',
            allowOutsideClick: false,
            showConfirmButton: false,
            html: '<div class="lds-ring"><div></div><div></div><div></div><div></div></div>'
        });

        $.ajax({
            url: '/Admin/GetCategory', // Replace with your controller endpoint URL
            type: 'GET',
            success: function (data) {
                // Clear existing table rows
                $('#CategoryTable tbody').empty();

                var serialNumber = 1; // Initialize serial number counter

                // Loop through fetched data and append to table
                $.each(data, function (index, item) {
                    // Handle null values for all fields
                    var nameValue = item.Name != null ? item.Name : 'NA';
                    var groupValue = item.Group != null ? item.Group : 'NA';
                    var descriptionValue = item.Description != null ? item.Description : 'NA';
                    var imageUrl = item.ImageUrl != null ? item.ImageUrl : 'NA'; // Image URL

                    var enabledValue = item.Enabled != null ? item.Enabled : 'NA';

                    // Check if imageUrl is 'NA' (Image Not Available)
                    var imageHtml = imageUrl != 'NA' ? '<img src="' + imageUrl + '" alt="Image" style="width: 100px; height: auto;">' : '<span>Image Not Available</span>';

                    // Append data along with icons to table
                    $('#CategoryTable tbody').append(
                        '<tr>' +
                        '<td>' + serialNumber + '</td>' + // Add serial number column
                        '<td>' + nameValue + '</td>' +
                        '<td>' + groupValue + '</td>' +
                        '<td>' + descriptionValue + '</td>' +
                        '<td>' + imageHtml + '</td>' + // Image column
                        '<td>' + enabledValue + '</td>' +
                        '<td>' +
                        '<a href="#" class="btn btn-primary btn-sm"><i class="fa fa-edit" aria-hidden="true"></i></a> ' + // Edit button
                        '<a href="#" class="btn btn-danger btn-sm" disabled><i class="fa fa-trash" aria-hidden="true"></i></a>' + // Delete button
                        '</td>' +
                        '</tr>'
                    );

                    serialNumber++; // Increment serial number for next row
                });

                // Hide loading spinner
                Swal.close();
            },
            error: function (xhr, status, error) {
                console.error('Error fetching data:', error);
                // Hide loading spinner in case of error
                Swal.close();
            }
        });
    }





    $('#add-new-cat').click(function (e) {
        $('#aknoModal').modal("show");
    });

    $('#fuImage').on('change', function () {
        var file = this.files[0];
        var maxSize = 500 * 1024; // 500 KB
        var maxWidth = 300; // Maximum width
        var maxHeight = 300; // Maximum height
        var allowedExtensions = /\.(jpg|jpeg|png|gif|svg)$/i; // Allowed file extensions

        // Check file size
        if (file.size > maxSize) {
            // Display Swal alert for file size validation
            Swal.fire({
                title: 'File Size Limit Exceeded',
                text: 'The selected image exceeds the size limit of 500 KB.',
                icon: 'warning',
            });

            // Clear the file input
            $(this).val('');
            return;
        }

        // Check file extension
        if (!allowedExtensions.test(file.name)) {
            // Display Swal alert for file extension validation
            Swal.fire({
                title: 'Invalid File Type',
                text: 'Please upload files with extensions .jpg, .jpeg, .png, .gif, or .svg only.',
                icon: 'warning',
            });

            // Clear the file input
            $(this).val('');
            return;
        }

        // Create a FileReader object
        var reader = new FileReader();

        // Read the image file as a data URL
        reader.readAsDataURL(file);

        // Set up the onload event handler
        reader.onload = function (event) {
            // Create a new image element
            var image = new Image();

            // Set the src attribute of the image to the data URL
            image.src = event.target.result;

            // Set up the onload event handler for the image
            image.onload = function () {
                // Check image dimensions
                if (this.width > maxWidth || this.height > maxHeight) {
                    // Display Swal alert for image dimensions validation
                    Swal.fire({
                        title: 'Invalid Image Dimensions',
                        text: 'The selected image dimensions should not exceed 300x300 pixels.',
                        icon: 'warning',
                    });

                    // Clear the file input
                    $('#fuImage').val('');
                }
            };
        };
    });




    $('#btnSave').on('click', function () {
        $('.error').remove();
        let isValid = 1;

        // Validate Name
        var name = $('#txtCatName').val();
        if (name === '') {
            $('#txtCatName').after('<span class="error text-danger">Name is required</span>');
            isValid = 0;
        }

        var group = $('#ddlCatGroup option:selected').val();
        if (group === '0') {
            $('#ddlCatGroup').after('<span class="error text-danger">Group selection is required</span>');
            isValid = 0;
        }

        var desc = $('#txtCatDesc').val();
        if (desc === '') {
            $('#txtCatDesc').after('<span class="error text-danger">Description is required</span>');
            isValid = 0;
        }

        var fuImage = $('#fuImage')[0].files[0];
        if (!fuImage) {
            $('#fuImage').after('<span class="error text-danger">Image is required</span>');
            isValid = 0;
        } else {
            var allowedExtensions = /(\.jpg|\.jpeg|\.png|\.gif|\.svg)$/i;
            if (!allowedExtensions.exec(fuImage.name)) {
                alert('Please upload file having extensions .jpeg/.jpg/.png/.gif/.svg only.');
                $('#fuImage').val('');
                isValid = 0;
            }
        }

        var status = $('#ddlStatus option:selected').val();
        if (status != 'Y' && status != 'N') {
            $('#ddlStatus').after('<span class="error text-danger">Invalid status selection</span>');
            isValid = 0;
        }

        if (isValid) {
            var formData = new FormData();
            formData.append('Name', name);
            formData.append('Group', group);
            formData.append('Description', desc);
            formData.append('ImageFile', fuImage);
            formData.append('Enabled', status);
            console.log(formData);
            // Show loading spinner
            Swal.fire({
                title: 'Please wait...',
                allowOutsideClick: false,
                showConfirmButton: false,
                html: '<div class="lds-ring"><div></div><div></div><div></div><div></div></div>'
            });
            $.ajax({
                url: '/Admin/AddCategory',
                type: 'POST',
                processData: false,
                contentType: false,
                data: formData,
                success: function (data) {
                    // Hide modal
                    $('#aknoModal').modal("hide");
                    // Check if the response indicates success
                    if (data.success) {
                        // Handle success response
                        Swal.fire({
                            title: data.message,
                            icon: "success",
                        }).then((result) => {
                            if (result.isConfirmed) {
                                // Call fetchData function after clicking OK button
                                fetchData();
                            }
                        });

                    } else {
                        // Handle failure response
                        Swal.fire({
                            title: data.message,
                            icon: "error",
                        }).then((result) => {
                            if (result.isConfirmed) {
                                // Call fetchData function after clicking OK button
                                fetchData();
                            }
                        });
                    }
                },
                error: function (xhr, textStatus, errorThrown) {
                    fetchData();
                    // Hide modal
                    $('#aknoModal').modal("hide");
                    // Handle error response
                    Swal.fire({
                        title: 'Error occurred',
                        text: errorThrown,
                        icon: "error",
                    }).then((result) => {
                        if (result.isConfirmed) {
                            // Call fetchData function after clicking OK button
                            fetchData();
                        }
                    });
                }
            });

        }
    });
</script>

Step 7. Create a Modal Class for each property as per the requirement below

using Microsoft.AspNetCore.Http;

namespace Domain.Admin
{
    public class ProductCategory
    {
        public string Action {  get; set; }
        public int? ID { get; set; }
        public string Name { get; set; }
        public string Group { get; set; }
        public string Description { get; set; }
        public string ImageName { get; set; }
        public IFormFile ImageFile { get; set; }
        public string ImageUrl { get; set; }
        public string Enabled { get; set; }
        public string Created { get; set; }
        public string Modified { get; set; }
        public string ModifiedBy { get; set; }
        public string ModifiedHost { get; set; }
    }

    public class FileUploadResponse
    {
        public bool Success { get; set; }
        public string FileName { get; set; }
    }
}

Step 8. Implementing Controller Logic for Saving Categories with File Upload to Mega

   [HttpPost]
   public async Task<IActionResult> AddCategory([FromForm] ProductCategory cat)
   {
       try
       {
           // Check if image file is provided
           if (cat.ImageFile != null && cat.ImageFile.Length > 0)
           {
               // Upload the file to Mega.nz and get the response
               var uploadResponse = await UploadFileToMega("MegaUserId", "MegaPassword", cat.ImageFile.OpenReadStream(), cat.ImageFile.FileName);

               // Check if the upload was successful
               if (uploadResponse.Success)
               {
                   // Once uploaded, set the Image property of the category to the file name
                   //cat.Image = uploadResponse.FileName; // Replace this with the Mega.nz link if available

                   // Perform the database operation only if the file upload was successful
                   cat.Action = "INSERT";
                   cat.ImageName = uploadResponse.FileName;
                   var res = await _admRepo.AddProductCategory(cat);
                   dynamic responseJson = new { };
                   if (res.Result == 1)
                   {
                       // Create a JSON object with the success message
                       responseJson = new
                       {
                           success = true,
                           message = "Category added successfully"
                       };
                   }
                   else
                   {
                       responseJson = new
                       {
                           success = false,
                           message = "Category addition failed"
                       };
                   }
                   return Json(responseJson);
               }
               else
               {
                   // Handle the case where the file upload failed
                   return Json(new { success = false, message = "File upload failed" });
               }
           }

           // If no image file was provided, you might need to handle this case as well

           return Json(new { success = false, message = "No image file provided" });
       }
       catch (Exception ex)
       {
           // Handle exception
           return Json(new { success = false, message = "An error occurred" });
       }
   }

Step 9. Implementing Upload File/Images to Mega Cloud

Before this make sure you have created a Uploads folder in the root directory and a Images folder. The images folder should be located in the Uploads folder in Mega Cloud.

#region----------------Upload File To Mega Clould Drive---------------------
public async Task<FileUploadResponse> UploadFileToMega(string email, string password, Stream fileStream, string fileName)
{
    try
    {
        var client = new MegaApiClient();
        await client.LoginAsync(email, password);

        // Specify the folder where you want to upload the file
        var rootNode = await client.GetNodesAsync();
        var uploadsFolder = rootNode.FirstOrDefault(n => n.Type == NodeType.Directory && n.Name == "Uploads");

        // Get the list of all folders within the "Uploads" folder
        var uploadsFolders = await client.GetNodesAsync(uploadsFolder);

        // Search for the "Images" folder within the list of folders
        var imagesFolder = uploadsFolders.FirstOrDefault(n => n.Type == NodeType.Directory && n.Name == "Images");

        if (imagesFolder == null)
        {
            // Create "Images" folder if it does not exist
            imagesFolder = await client.CreateFolderAsync("Images", uploadsFolder);
        }

        // Generate a unique filename using GUID
        string uniqueFileName = Guid.NewGuid().ToString("N") + Path.GetExtension(fileName);

        // Upload the file to the "Images" folder with the unique filename
        await client.UploadAsync(fileStream, uniqueFileName, imagesFolder);

        await client.LogoutAsync();

        return new FileUploadResponse { Success = true, FileName = uniqueFileName };
    }
    catch (Exception ex)
    {
        // Log the error or handle it appropriately
        Console.WriteLine($"An error occurred during file upload: {ex.Message}");
        return new FileUploadResponse { Success = false, FileName = null };
    }
}

#endregion------------------------------------------------------------------

Step 10. Retrieving Images from Mega Cloud Storage

In this step, we focus on retrieving images from Mega Cloud storage that were previously uploaded alongside category data. Leveraging the backend logic we implemented earlier, we'll now integrate functionality to fetch these images and display them in our application's user interface.

#region------------------Retive the Image from Mega-------------------------
private async Task RetrieveImagesFromMega(List<ProductCategory> categories)
{
    // Mega account credentials
    string email = "MegaUserId";
    string password = "MegaPassword";

    // Initialize MegaApiClient
    var client = new MegaApiClient();

    try
    {
        // Login to Mega account
        await client.LoginAsync(email, password);

        // Iterate through each category and retrieve the image from Mega
        foreach (var category in categories)
        {
            // Retrieve the image file from Mega if ImageName is not null
            if (!string.IsNullOrEmpty(category.ImageName))
            {
                // Search for the image file by name in Mega
                var fileNode = client.GetNodes().FirstOrDefault(n => n.Name == category.ImageName);

                // If the image file exists, download it and convert to base64
                if (fileNode != null && fileNode.Type == NodeType.File)
                {
                    using (var stream = client.Download(fileNode))
                    using (var ms = new MemoryStream())
                    {
                        stream.CopyTo(ms);
                        var imageBytes = ms.ToArray();
                        var base64String = Convert.ToBase64String(imageBytes);
                        category.ImageUrl = "data:image/jpeg;base64," + base64String;
                    }
                }
                else
                {
                    // Handle case where image file is not found or not accessible
                    category.ImageUrl = null;
                }
            }
        }
    }
    finally
    {
        // Logout from Mega account
        await client.LogoutAsync();
    }
}
#endregion-------------------------------------------------------------------

Conclusion

In this article, we've covered the integration of file upload functionality with Mega Cloud storage. From frontend setup to backend implementation, each step has been detailed thoroughly. Leveraging tools like SweetAlert2 and Mega.APIClient, we've ensured a seamless user experience and robust data management.

By utilizing Mega Cloud storage, your application gains enhanced security and scalability. The user-friendly interface and smooth integration contribute to an improved user experience. Moving forward, continue exploring Mega Cloud storage and other tools to elevate your application further.

Output

Thank you for joining us on this journey to unlock the potential of Mega Cloud storage in your web application. Happy coding!


Similar Articles