When attempting to update a file using AJAX after it has been modified, Chrome displays the error message net::ERR_UPLOAD_FILE_CHANGED

I am facing an issue with a basic HTML form that utilizes AJAX to send a selected file to an API endpoint. The problem arises when I follow these steps:

  1. Click on the Upload button and initiate a POST request to upload the file
  2. Modify the selected file using a text editor without re-selecting it in the file picker
  3. Click on the Upload button again, triggering a second POST request

Chrome throws an error for the second request: net::ERR_UPLOAD_FILE_CHANGED. Interestingly, if you make changes to the file before the initial upload, it goes through without any issues. This error only occurs during the second upload after changing the file following a successful initial upload. I have tested this scenario with CSV files by editing them in a text editor.

Unfortunately, there doesn't seem to be a straightforward solution to isolate and resolve this error.

Is there a workaround for this particular problem?

If not, is there a way to catch this specific error and provide a meaningful message to the user? The promise returned by Fetch does not contain detailed information about this error. The only mention of ERR_UPLOAD_FILE_CHANGED is in the browser's developer console.

I am quite certain that around a year ago (early 2019), there weren't any issues with this process as users had the ability to re-upload modified files seamlessly within our UI flow. Now we are forced to prompt the user to pick the file again. Hence, I suspect that this error might have been introduced with a recent Chrome update.

Below is a simplified snippet of the code being used:

<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>

EDIT: This bug has been labeled as WontFix on bugs.chromium.org: https://bugs.chromium.org/p/chromium/issues/detail?id=1086707#c7

Answer №1

An effective workaround is to add a complete parameter to the AJAX call (or something similar to a finally call that always executes) and include code to reset the form. I've observed that reattaching the file resolves the issue. While not a permanent solution, it does help in handling or avoiding the error.

By implementing this approach, users can easily re-upload the file if needed, as they will be prompted to select the file again.

See the example below:

$.ajax({
    url: this.action,
    type: this.method,
    data: this.data,
    success: function (response) { 
        // action on success
    },
    error: function (result) {
        // action on error
    },
    complete: function (data) {
        $('#uploadForm')[0].reset(); // resets the form fields
    }
});

Answer №2

Utilizing the javascript File Reader, I was able to obtain a more detailed error message. When the file is modified and the button is clicked for the second time, the FileReader now produces a clearer error:

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

This error can be caught and shown to the user, prompting them to re-select the file.

See below snippet for reference:

<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) {
                        // error handling 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> 

Unfortunately, it appears there is no immediate solution to this issue as of June 2020. There is an open bug on Chromium related to this problem:

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

Answer №3

To clear the file input field after displaying messages or processing data, simply reset it with the following code:

$('#file').val("");

Answer №4

Working with Angular, I found these two steps to be effective in resolving the problem:

1] Perform a form reset when an error occurs -

this.form.reset()

2] Reset the value of the HTML input element -

<input type="text" #textInput (change)="OnInputChange($event)" (click)="$event.target.value = ''"/>

Answer №5

Avoid accessing a file that has been changed without explicit user action to prevent security risks.

Instead, save the uploaded file in memory:


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

Retrieve the file content from memory when the "Send" button is pressed:

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

While it may not guarantee sending the latest version of the file, ensure that you are sending the originally uploaded content.

Be mindful of memory usage and the asynchronous nature of file reading APIs to handle potential errors with modified content even when storing it in memory.

Answer №6

$("#id_for_your_upload_button").on('click', function(){
 $("#id_for_your_file_input").val('');
});

To address a browser exception, include the jQuery script above to clear the file input whenever it is clicked on. This ensures that any current selection is removed.

Answer №7

One way to handle this situation is by comparing the file's lastModified property before and after each upload button click. If there is a difference, you can reset the form values.

To learn more about File.lastModified, you can refer to this link: https://developer.mozilla.org/en-US/docs/Web/API/File/lastModified

Alternatively, a more efficient solution would be to read the file into an ArrayBuffer and then proceed with the upload process using that data.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble with my Slack Bot development due to an unexpected error

While attempting to create a Slack Bot in Node, I consistently encounter an error when running npm start in my terminal: The error seems to be located in the Vow.js file. Despite double-checking everything, I can't seem to pinpoint the issue. For gui ...

Use angular js to dynamically load a template via an ajax request

I am trying to send an AJAX request in order to retrieve a JSP/HTML page for the templateUrl of a modal. Here is the code I have written: var modalInstance = $uibModal.open({ animation: $scope.animationsEnabled, te ...

Using Redux to Implement Conditional Headers in ReactJS

I am planning to develop a custom component named HeaderControl that can dynamically display different types of headers based on whether the user is logged in or not. This is my Header.jsx : import React from 'react'; import { connect } from &a ...

Is it possible to view the code within the .js files located in the api directory of NextJS using web browsers?

Is it possible to view the code of ".js files" in the "api folder" of NextJS using browsers? I came across a post on Stack Overflow where someone asked if Next.js API is back-end, and one of the answers stated: The back-end or server-side of Next.js res ...

Implementing dynamic Devise user authentication forms using AJAX technology

I need help with rendering my custom sign up/sign in forms using devise 2.2.0 and AJAX. Instead of altering the original devise SessionsController to return format.js, I created a new controller solely for rendering the 'devise/sessions/new' temp ...

What is the purpose of importing React from "react" in a .jsx file? Is there any distinction between the .jsx and .js extensions?

Typically, we use it to write JSX syntax within .js files. ...however, since I've already specified the extension as .jsx, why do we still need to import the react module? I've attempted to find the answer, but it remains unclear in all my resea ...

I am facing the issue of only one ajax script functioning properly even though I have

I have encountered a confusing issue with two loadmore scripts that are triggered by different buttons. The problem is that when I click the second button, it loads the content that should actually be loaded by the first button. The first button, however, ...

Typescript is throwing an error when trying to use MUI-base componentType props within a custom component that is nested within another component

I need help customizing the InputUnstyled component from MUI-base. Everything works fine during runtime, but I am encountering a Typescript error when trying to access the maxLength attribute within componentProps for my custom input created with InputUnst ...

How can I properly reset a timeout duration?

I'm currently working with a function that looks like this: function blabla(){ ... setTimeout(() => { //do some stuff }, 10000) } My question is, how can I reset the time of the timeout (10000) if the function was called and ...

What is the syntax for passing a string to C#/ASP.NET through the use of $.ajax()?

Everything is functioning properly [System.Web.Services.WebMethod] public static string Save_HH() { return "abc"; } This particular aspect is not functioning as expected [System.Web.Services.WebMethod] public static string Save_HH(string myString) ...

What steps should I take to activate JavaScript type checking in Vue files within Visual Studio Code?

After much exploration, I have successfully configured Visual Studio Code to perform type checking for JavaScript within JS files. This feature highlights any bad code and provides explanations for why it is considered as such here. However, this function ...

Guidance on retrieving a boolean value from an asynchronous callback function

I'm looking to determine whether a user is part of a specific group, but I want the boolean value returned in the calling function. I've gone through and debugged the code provided below and everything seems to be working fine. However, since my ...

Utilize INTERFACE-driven capabilities in ReactJS to dynamically render components based on a variable

How can interface-based functionality be used to render components based on tab selection? If we have 3 components as follows: OneTimeOnlyScheduleComponent DailyScheduleComponent WeeklyScheduleComponent We aim to have all of these components implement t ...

Conceal information on-the-fly using React

I am seeking a way to dynamically hide irrelevant items based on their tags. This functionality should only be applied to tags with a "taglevel" higher than 1. For instance, if I select the tag "books," only the tags "adventure" and "classic" should be d ...

Unexpected issue with AngularJS Select2 multiple feature: ng-selected not functioning as expected

I have been working with the code below to select an item if it is present in the filters: <div ng-repeat="category in categories.data" ng-model="div1"> <div ng-repeat="(key, value) in category" mg-model="div1.div2"> ...

Sort and filter tables with ease using column-specific options

I am looking for assistance in implementing a table sorter with ajax specifically for individual columns. Is there an inbuilt method to trigger an ajax call when filtering a column? Here is the source code I have: theme: 'blue', widthFixed: tru ...

The toggleClass function in jQuery seems to be malfunctioning when used with an

My current setup involves two buttons, "Approve" and "Unapprove", as well as an image of a loading spinner. Initially, only the Approve button is visible while the Unapprove button and spinner image are hidden. When the user clicks on the "Approve" button ...

Implementing Twitter Login with Vue, Vuex, and Firebase

Exploring a Twitter login option for my sports social media dashboard project, I followed a helpful tutorial. While I've successfully implemented the HelloWorld component and retained the app.vue and main.js components, I encountered an error stating ...

Guide on utilizing mongoose for handling multiple increment operations

Currently, I am developing a program that tracks different "accepts" and "denies". In this project, I am utilizing the findOneAndUpdate function from mongoose. However, I am encountering some issues with achieving the desired functionality. The data I am w ...

JavaScript code for displaying data sequentially one at a time

Hey there, I've developed a function that pulls data from a jsonp file. However, I'm looking to display this data one by one - starting with the vendor's name followed by their policyUrl. If you want to check out the source code, click on t ...