web-dev-qa-db-ja.com

AJAXが変更された後にファイルを再アップロードすると、Chromeでnet :: ERR_UPLOAD_FILE_CHANGEDが発生します

選択したファイルをAJAX=経由でAPIエンドポイントに送信する単純なHTMLフォームがあります。

次の手順を実行した場合:

  1. アップロードボタンを押して、POSTファイルのアップロードをリクエストします。
  2. ファイルピッカーで再度選択せずに、ファイルシステムで選択したファイルを(テキストエディターで)変更します。
  3. もう一度[アップロード]ボタンを押して、2番目にPOST request

Chromeは2番目のリクエストをnet::ERR_UPLOAD_FILE_CHANGEDのエラーで失敗します。最初のアップロードの前にファイルを変更した場合、ファイルは問題なくアップロードされることに注意してください。エラーは、最初のアップロードが正常に完了した後でファイルを変更したときに、2番目のアップロードでのみ発生します。これをCSVファイルでテストし、テキストエディターで変更しています。

そのエラーを分離する方法はないようです。

これを回避する方法はありますか?

そうでない場合は、この特定のエラーをキャッチして、ユーザーに意味のあるメッセージを表示することができます。 Fetchがpromiseで返すエラーには、これに関する特定の情報はありません。 ERR_UPLOAD_FILE_CHANGEDが表示される唯一の場所は、ブラウザの開発コンソール内です。

変更されたファイルを再アップロードする可能性があり、UIフローでうまく機能したので、約1年前(2019年初頭)に問題がなかったと確信しています。ここで、ユーザーにファイルを再度選択させる必要があります。つまり、これは最近の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>
5
Martin Taleski

いいえ、ユーザーがファイルを既に別のファイルに変更している場合、ユーザーが明示的なユーザーアクションなしにこのファイルにアクセスすることはできません(すべきではありません)。

ユーザーがアップロードしたときに、ファイルをメモリに保存できます。


document.getElementById('fileInput').addEventListener('change', function() {
   saveFileConentInMemory(this.files[0].arrayBuffer());
});

そして、ユーザーが「送信」ボタンを押すと、メモリからこのコンテンツを取得して送信します

button.addEventListener('click', () => {
   const file = getFileContentFromMemeory();
   send(file);
})

はい、確実に最新バージョンのファイルを送信することはできませんが、アップロードされたコンテンツを送信することを確認する必要があります。

また、メモリの消費とファイルの読み取りの非同期APIに注意する必要があります(メモリに書き込んでも、変更されたコンテンツに関するこのエラーが発生する可能性があります)

0
maksimr

アップロードボタンのクリックの間にfile.lastModifiedを確認し、異なる場合はフォームの値をリセットします。

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

より良い解決策は、ファイルをArrayBufferに読み込んでアップロードすることです。

0
Gungnir