更改后使用 AJAX 重新上传文件会导致 Chrome 中的 net::ERR_UPLOAD_FILE_CHANGED

Mar*_*ski 19 javascript ajax google-chrome file-upload

我有一个简单的 HTML 表单,它通过 AJAX 将选定的文件发送到 API 端点。

如果我执行以下步骤:

  1. 按上传按钮并发出 POST 请求以上传文件
  2. 更改文件系统上的选定文件(在文本编辑器中),而无需在文件选择器中再次选择它。
  3. 再次按下上传按钮,并作为第二个 POST 请求

Chrome 将失败第二个请求并显示错误:net::ERR_UPLOAD_FILE_CHANGED。请注意,如果您在初始上传之前更改文件,则上传文件将没有问题。该错误仅在第二次上传时发生,当您在首次成功上传后更改文件时。我正在用 CSV 文件对此进行测试,并在文本编辑器中更改它们。

似乎没有办法隔离该错误。

有没有办法解决?

如果没有,是否可以捕获此特定错误,并向用户显示有意义的消息。Fetch 在承诺中返回的错误没有关于此的具体信息。我看到的唯一地方ERR_UPLOAD_FILE_CHANGED是在浏览器开发控制台中。

我很确定大约一年前(2019 年初)没有任何问题,因为可以重新上传更改的文件,在我们的 UI 流程中很好地发挥了作用。现在我们需要强制用户再次选择文件。所以我假设这是在最近的 chrome 更新中引入的。

这是代码的简化片段:

<html>
<head>
        <script type='text/javascript'>
        document.addEventListener("DOMContentLoaded", function(){

                const button = document.querySelector('#btnSubmit');

                button.addEventListener('click', () => {
                        const form = new FormData(document.querySelector('#theForm'));
                        const url = '/my-api'
                        const request = new Request(url, {
                                method: 'POST',
                                body: form
                        });
        
                        fetch(request).then(function() {
                                console.log("ok");
                        }).catch(function(err) {
                                console.log(err);
                        });
                });
        });
        </script>

</head>
<body>
        <form enctype="multipart/form-data" action="" method="post" id='theForm'>
                <input type="file" name="csvfile" id="csvfile" value="" /></td>
                <input type="button" name="uploadCSV" value="Upload" id='btnSubmit'/>
        </form>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

编辑:该错误在 bugs.chromium.org 上被标记为 WontFix:https ://bugs.chromium.org/p/chromium/issues/detail ? id = 1086707#c7

Duc*_*ing 7

一个快速的解决方法是在completeAJAX 调用中包含一个参数(或任何等同于finally始终被调用的调用)并添加重置表单的代码。我注意到再次附加文件可以解决它。虽然我很欣赏这不是问题的真正解决方案,但它确实提供了处理或避免该错误的方法。

这样,如果用户出于任何原因需要重新上传文件,他们将不得不再次选择该文件。

下面的例子:

$.ajax({
    url: this.action,
    type: this.method,
    data: this.data,
    success: function (response) { 
        // success scenario
    },
    error: function (result) {
        // error scenario
    },
    complete: function (data) {
        $('#uploadForm')[0].reset(); // this will reset the form fields
    }
});
Run Code Online (Sandbox Code Playgroud)


Mar*_*ski 6

我设法使用 javascript 文件阅读器获得了更具描述性的错误。在更改文件并第二次按下按钮后, FileReader 会抛出一个更具描述性的消息:

DOMException: The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.

至少这是一个可以被捕获并显示给用户的错误,因此他们知道他们需要重新选择文件。

这是片段:

<html>
    <head>
        <title>Test</title>
        <script type='text/javascript'>
        document.addEventListener("DOMContentLoaded", function(){

            const button = document.querySelector('#btnSubmit');

            button.addEventListener('click', () => {
                let inputElement = document.getElementById('csvfile');

                for (let i = 0; i < inputElement.files.length; i++) {
                    const file = inputElement.files[i];

                    console.log(file);

                    const reader = new FileReader();
                    reader.readAsText(file, "UTF-8");

                    reader.onload = function (evt) {
                        console.log(evt.target.result);
                    }

                    reader.onerror = function (err) {
                        // read error caught here
                        console.log(err);
                        console.log(err.target.error);
                    }

                }

            });
        });
        </script>

    </head>
    <body>
        <form enctype="multipart/form-data" action="" method="post" id='theForm'>
                <input type="file" name="csvfile" id="csvfile" value="" />
                <input type="button" name="uploadCSV" value="Upload" id='btnSubmit'/>
        </form>
    </body>
</html> 
Run Code Online (Sandbox Code Playgroud)

目前似乎没有办法解决这个问题(2020 年 6 月)。Chromium 上有一个未解决的错误:

https://bugs.chromium.org/p/chromium/issues/detail?id=1084880&q=ERR_UPLOAD_FILE_CHANGED&can=2

  • 能够简单地“刷新”本地文件内容是我的可视化应用程序的重要组成部分。这真是太糟糕了。 (2认同)

小智 -1

我只是在上传按钮单击之间检查 file.lastModified ,如果不同则重置表单值。

https://developer.mozilla.org/en-US/docs/Web/API/File/lastModified

更好的解决方案是将文件读入 ArrayBuffer 并上传。

  • 文件更改后,file.lastModified 仍显示为旧的上次修改日期。看来浏览器没有权限读取更改后的文件。请参阅下面我的答案:/sf/answers/4349886621/ (2认同)