如何让用户确认 ASP.NET Core 6 中的文件覆盖

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

我正在使用 ASP.NET Core 6 构建文件上传 Web 应用程序,我希望用户能够确认是否覆盖现有文件。该应用程序允许上传多个文件

问题:

这是我的表格:

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

这是控制器操作:

[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);
    }
}

我简化了上面的代码以免添加太多细节

尝试次数

我已经尝试 AJAX 调用来停止 POST 请求并添加一些逻辑,但我似乎无法访问服务器上的文件夹甚至无法检查文件是否已经存在存在

$("#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");

为了简单起见,我简化并删除了上面代码中的右大括号

如果文件已存在,您 POST 上传文件可能 return 出现 409 冲突状态。 UI 然后会在第一次发布时检测到这一点,并显示一个弹出窗口。如果用户选择 'continue',则 POST 可以包含一个查询参数,表示用户已确认允许 OK。像这样:

[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);
    }

}

您可以执行以下操作,

  1. 使用 AjaxRequest 提交表单(通过防止默认)
  2. 如果所有文件都是新的,在 Controller Action 中保存文件
  3. 如果有任何重复文件,请不要保存文件。向客户端发送一条消息,指出这些文件是重复的,要覆盖这些文件吗?
  4. 如果用户说“是”,使用附加参数再次发送相同的 AjaxRequest 并保存所有文件(覆盖重复文件)
  5. 如果用户说“否”,则无需执行任何操作

让我们转到代码

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);
});

控制器

[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" });
        }
    }