Search code examples
reactjsfine-uploader

FineUploader not working after first upload


I've implemented FineUploader in my React app to upload files to my Azure Blob Storage and it's working fine except for one issue.

After uploading a file successfully, if I try uploading another one, FineUploader is not allowing me to select a new file. Clicking the select button opens up the dialog box to let me select a file but clicking the file to select it simply does nothing. I don't see any errors either.

Any idea what could be causing this issue?

Here's my implementation of FineUploader in my app:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import FineUploaderAzure from 'fine-uploader-wrappers/azure'

// Components
import Gallery from './gallery/index';

// Actions
import * as fileActions from '../../../../actions/file-actions';

// Instanciate FineUploader
const uploader = new FineUploaderAzure({
    options: {
        cors: {
            expected: true,
            sendCredentials: false
        },
        signature: {
            endpoint: 'https://api.myapp.com/files/get/sas'
        },
        request: {
            endpoint: 'https://myaccount.blob.core.windows.net/my-container'
        },
        validation: {
            itemLimit: 1
        }
    }
})

class FileUploader extends Component {

    constructor(props) {

        super(props);
        this.saveFileInfo = this.saveFileInfo.bind(this);
    }

    componentDidMount() {

        uploader.on('complete', (id, name, responseJSON, xhr) => {

            const originalName = uploader.methods.getName(id);
            const blobName = uploader.methods.getBlobName(id);
            const fileSize = uploader.methods.getSize(id);

            this.saveFileInfo(originalName, blobName, fileSize);
        })
    }

    saveFileInfo(fileName, blobName, fileSize) {

        // Gather necessary information
        const accountId = this.props.accountId;
        const id = this.props.id;
        const folderId = this.props.activeFolder.id;
        const files = [
            {
                fileName: blobName,
                displayName: fileName,
                fileSize: fileSize
            }
        ];

        // Call backend API to save file info in database
        this.props.actions.createFileRecords(accountId, bizObject, id, privilegeLevel, folderId, files);

        // Close modal
        const modalId = this.props.modalId;
        return this.props.handleClose(modalId, false);
    }

    render() {

        return (
            <div style={{ position: 'fixed', zIndex: 250000990 }}>
                <div className="modal-wrapper">
                    <div className="height-100 width-100" style={{ background: 'transparent', position: 'absolute', left: '0', top: '0' }}></div>
                    <div className="modal-window vertical-center">
                        <div className="modal-controls padding-right-20 padding-top-10" style={{ height: '50px', position: 'absolute', right: '0', top: '0', lineHeight: '40px', borderColor: 'transparent !important' }}>
                            <a className="modal-control mc-help"></a>
                            <a className="modal-control mc-close" onClick={e => this.props.handleClose(this.props.modalId, false)}></a>
                        </div>
                        <div className="width-100 height-100 border-radius border-black-w1-1" style={{ overflow: 'hidden', background: 'black !important', borderColor: 'black' }}>
                            <Gallery uploader={uploader} onComplete={this.handleFileUpload} />
                        </div>
                        <div style={{ position: 'absolute', bottom: '17px', left: '17px' }}>

                            {/* Privilege Level Selector */}
                            {this.renderPrivilegeLevels()}
                            <span className="app-btn app-btn-lg margin-left-20">Uploading into Folder: <strong>{this.props.activeFolder.name}</strong></span>

                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

function mapStateToProps(state, ownProps) {

    return {
        modalId: ownProps.modalId,
        accountId: ownProps.accountId,
        id: ownProps.id,
        folders: ownProps.folders,
        activeFolder: ownProps.activeFolder,
        fileUpload: state.files.fileUpload,
        errors: state.files.errors,
        handleClose: ownProps.handleClose
    }
}

function mapDispatchToProps(dispatch, ownProps) {

    return {
        actions: bindActionCreators(fileActions, dispatch)
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(FileUploader)

Solution

  • As explained in the comment the itemLimit: 1 option is limiting the total number of upload for that Uploader to 1.

    Since what you are trying to achieve is actually avoiding multiple upload at once you can use the option multiple: false to block selection of multiple files.

    Also, to avoid users adding more files while others are still uploading, you can use a custom validation where you check if some other files are in progress, for example:

       options: {
          ..., //other options
          callbacks: {
             onValidate: function (file) {
               if(getInProgress() > 0){
                  return false;
               }        
               return true;        
          }
       }
    

    Note that the onValidate events is called before the default Fine Uploader validators