简体   繁体   中英

Reading a local file a _second_ time using the html5 file reader API

I am currently working on some small helper utility. The approach is an in-page web app which is typically loaded from the local file system. That all works. Inside that app I need to be able to load and process local files (storing and reloading a profile). That works so far, but I have a problem left where I would like to ask for help:

I am using the filereader.js wrapper around the html5 file reader API. Things work so far, I am able to select, read and process a file in-page. Great! I even can process several files one after another. However there is one problem where I don't know how to start debugging it: I can not read a specific file a second time . I can select it, sure, but it is not read, thus not processed. It looks like there are no events generated at all by the file reader API. This might be connected to either caching or the prior usage of the file not having been terminated by me correctly, I have no idea.

Here is the relevant code:

My FileReader JS function:

function FileReader( selector, options ) {
    var options = $.extend({
        clicked:  function(){},
        payload:  function(){},
        selected: function(){}
    }, options||{} );
    var widget   = convert( selector );
    var selector = widget.find( 'input:file');

    function clicked( event ) {
        event.stopPropagation();
        // highlight button as user feedback
        highlight();
        // raise the file selection dialog
        selector.click();
        // signal action to element
        options.clicked();
    }

    function convert( selector ) {
        var widget = $( selector );
        // create new content for widget
        var hotspot = $( '<a class="hotspot">' + widget.html() + '</a>' ).bind( 'click', clicked );
        var selector = $( '<input type="file" style="display:none;" />' );
        // replace initial content of widget
        widget.empty().append( $('<form />').append(selector).append(hotspot) );
        widget.find( 'input:file' ).fileReaderJS( { accept: false,
                                                                                                readAsDefault: 'BinaryString',
                                                                                                on: { load: selected } } );
        return widget;
    }

    function highlight() {
        // flash button by changing the background color for 100 msecs
        widget.css( 'background-color', 'whitesmoke' );
        setTimeout( function(){ widget.css( 'background-color', 'transparent' ); }, 100 );
    }

    function selected( event, file ) {
        // process payload
        options.payload( event.target.result );
        // signal event to controlling element
        options.selected();
    }

    return {}
} // FileReader

This method is called with '#wProfileImport' as value of the argument selector , which actually works and converts the markup below

<span id="wProfileImport" class="control button">
    <img src="assets/img/profile-import.png">
</span>

such that it contains a (hidden) file input tag which is used to fire the file selection dialog (which works fine):

<span id="wProfileImport" class="control button">
    <form>
        <input type="file" style="display:none">
    </form>
    <a class="hotspot">
        <img src="assets/img/profile-import.png">
    </a>
</span>

Now when clicking the image the file selector is fired, I can select a local file and its content is handed over to the options.payload callback. As said all fine and working also for more than a single file one after another. The only problem that remains: being able to read in the same file again. No event is fired, no content read, nothing.

So my question is: what do I have to do the process a file a second time , if it is selected by the user?

This has to do with how the onchange event works in JavaScript.

If you have a text input and you type a word, let's say "bird" . You unfocus the field, this will cause the onchange event to trigger. If you then go back into the field and change the word, then without unfocussing change it back to "bird" and then unfocus the onchange event will not fire because the value didn't change.

Other events like onkeydown and onfocus will fire however.

See if you can find another event that you can use. Maybe onclick or onfocus . I do fear that these fire too early.

A workaround to to destroy the input once you read the file and render a new one in it's place. This way if the user selects the same file it will count as an onchange again.

Another possibility is to not use the onchange event but do the process once you press a submit button. You can get a reference to the file with:

var file = document.getElementById("#the_file_input").files[0];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM