Home > other >  How can I get user to confirm file overwrite in ASP.NET Core 6
How can I get user to confirm file overwrite in ASP.NET Core 6

Time:03-02

I'm building a file upload web application using ASP.NET Core 6 and I would like the user to be able to confirm whether or not to overwrite an existing file. The application allows for multiple file uploads

Questions:

  • where to check if the file exists? (i.e. client-side or on the server)
  • if on the client-side how to check if file exists on the server?
  • how to handle the POST request so that it can "wait" for user confirmation?
  • is this kind of "communication" with the user even possible in ASP.NET Core 6? or should I be using Blazor or Signal R (I'm really new to .NET)

This is my form:

<form method="POST" enctype="multipart/form-data">
    <input type="file" multiple name="files">
    <button type="submit" >Upload Files</button>
</form>

This is the controller action:

[HttpPost]
public async Task<IActionResult> UploadFiles(IEnumerable<IFormFile> files, string folders)
{
    foreach (var file in files)
    {
        string trimmedFileName = String.Concat(file.FileName.Where(c =>!Char.IsWhiteSpace(c)));

        var filePath = Path.Combine(folders, trimmedFileName);

        if (System.IO.File.Exists(filePath))
        {
            ViewBag.Error = $"File {trimmedFileName} already exists on the server";
            this.Redirect("UploadFiles");
        }

        using var filestream = System.IO.File.Create(filePath);

        await file.CopyToAsync(filestream);
    }
}

I have simplified the above code so as not too add too much detail

Attempts

I have tried AJAX calls to stop the POST request and add some logic but I don't seem to be able to access the folder on the server to even check if the file already exists

$("#uploadForm").submit(function(e){
e.preventDefault();
let files = $(".form-control-file")[0].files;

for (let i = 0; i < files.length; i  ){
    let url = $("#filePathUrl").val()   "/"   files[i].name;
    if(url){
        $.ajax({
            url: url,
            type: 'HEAD',
            error: function(){
                alert(files[i].name   " exists!");
            },
            success: function(){
                alert(files[i].name   " does not exist on server");

I have simplified and removed closing braces from the above code to keep things simple

CodePudding user response:

Your POST to upload the file could return a 409 Conflict status if a file already exists. The UI would then detect this on first posting, and show a popup. If the user selects 'continue', then the POST could include a query parameter to say the user has confirmed the OK is allowed. Something like this:

[HttpPost]
public async Task<IActionResult> UploadFiles(bool? allowOverwrite, IEnumerable<IFormFile> files, string folders)
{
    foreach (var file in files)
    {
        string trimmedFileName = String.Concat(file.FileName.Where(c =>!Char.IsWhiteSpace(c)));

        var filePath = Path.Combine(folders, trimmedFileName);

        if (!allowOverwrite.GetDefaultValue() && System.IO.File.Exists(filePath)) <---
        {
            ViewBag.Error = $"File {trimmedFileName} already exists on the server";
           
            return Conflict(); <---
        }

        using var filestream = System.IO.File.Create(filePath);

        await file.CopyToAsync(filestream);
    }

}

CodePudding user response:

Here's what you can do,

  1. Use AjaxRequest to submit the form (by preventing default)
  2. In Controller Action save files if all the files are new
  3. Dont save files if there is any duplicate. Send a message to the client stating that these files are duplicate, Do you want to overwrite these files?
  4. if user says "Yes", send the same AjaxRequest again with an additional parameter and Save all the files (with overwriting duplicate files)
  5. If user says "No", then nothing needs to be done

Lets move to code

JS

function processFiles(confirmOverwrite = false){
    const files = $(".form-control-file")[0].files;
    const formData = new FormData();
    
    files.forEach(file => formData,append('files[]', file));
    
    const folderName = 'Uploads';
    const url = $("#filePathUrl").val();
    $.ajax({
        url: url '?folders=' folderName '&confirmOverwrite=' confirmOverwrite,
        type: 'POST',
        data: formData,
        processData: false,
        success: (response) =>{
            if(response.Status){
                alert('Files uploadedn successfully');
            }
            else{
                if(response.Message){
                    if(confirm(response.Message   ' files already exist. Do you want to overwrite these?'){
                        processFiles(true);
                    }
                    else{
                        alert('Files not uploaded');
                    }
                }
            }
        },
        error: (a,b,c) => {
            console.error({a,b,c});
        }
    });
}
$("#uploadForm").submit(function(e){
    e.preventDefault();
    processFiles(false);
});

Controller

[HttpPost]
    public async Task<IActionResult> UploadFiles(IEnumerable<IFormFile> files, string folders, bool confirmOverwrite = false)
    {
        var existingFiles = new List<string>();
        var filesToBeSaved = new List<(IFormFile file, string filePath)>();
        foreach (var file in files)
        {
            string trimmedFileName = file.FileName.Replace(" ", "");

            var filePath = Path.Combine(folders, trimmedFileName);

            if (System.IO.File.Exists(filePath) && !confirmOverwrite)
            {
                existingFiles.Add(file.FileName   "("  trimmedFileName   ")");
            }
            else
            {
                filesToBeSaved.Add((file, filePath));
            }                
        }

        if (existingFiles.Any())
        {
            return Json(new { Status = false, Message = string.Join(", ", existingFiles) });
        }
        else
        {
            foreach (var (file, filePath) in filesToBeSaved)
            {
                using var filestream = System.IO.File.Create(filePath);
                await file.CopyToAsync(filestream);
            }
            return Json(new { Status = true, Message = "Success" });
        }
    }
  • Related