Как управлять проверкой в ​​AngularJS файла, который уже был загружен внутри виджета формы?

Моя модель AngularJS имеет два свойства: файловый объект vm.profile.file и текстовое значение, содержащее ссылку на загруженный на сервер файл vm.profile.resume. vm.profile.file проверяется по мере необходимости с ограниченным размером. Тем не менее, когда форма обновляется, ссылка, которая является приемлемой и передается на сервер, в порядке, но нет необходимости в том, чтобы файловый объект снова устанавливался на сервер. Как проверить форму, если ссылка на файл существует, а ненужный файловый объект пуст?

Я использую ng-file-upload.

Вот как выглядит форма: введите здесь описание изображения

Вот часть кода, который я использую:

    <div class="sj-section-content" flex="60">
        <md-card>
            <md-input-container>
                <div layout="row" layout-align="start center">
                    <md-button class="md-primary md-raised"
                               style="max-width: 150px; color: white;"
                               ngf-select
                               required
                               name="resume"
                               ngf-min-size="0MB"
                               ngf-max-size="1MB"
                               ng-model="vm.profile.file">
                        <span>{{!vm.profile.resume ? 'Select file' : 'Change'}}</span>
                    </md-button>
                    <md-button ng-if="vm.profile.resume" ng-click="vm.profile.file = {}" class="md-icon-button">
                        <md-icon md-font-icon="clear">clear</md-icon>
                    </md-button>
                </div>
                <div ng-if="vm.profile.file.name" layout="row" layout-align="start center">
                    <md-button class="md-icon-button" md-no-ink>
                        <md-icon md-font-icon="attachment">attachment</md-icon>
                    </md-button>
                    <div>{{vm.profile.file.name}}</div>
                </div>
                <div ng-messages="profileForm.resume.$error"
                     ng-if="profileForm.resume.$error && (profileForm.$submitted || profileForm.resume.$dirty)"
                     role="alert">
                    <div ng-if="profileForm.resume.$error.maxSize"
                         ng-message="maxSize">Max file size is 10MB</div>
                    <div ng-if="profileForm.resume.$error.required"
                         ng-message="required">Resume is a required field</div>
                </div>
            </md-input-container>
        </md-card>
    </div>

Служба API:

    ProfileApi.prototype.update = function update(model) {
        var deferred = $q.defer();

        Upload.upload({
            url: endpoint,
            method: 'PUT',
            data: model
        }).then(function success(response) {
            deferred.resolve(response.data);
        }, function error(response) {
            deferred.reject(response.data);
        });

        return deferred.promise;
    };

И на сервере:

exports.fileHandler = function(req, res, next) {
    var MAX_FILE_SIZE = 10 * 1000000;
    var FILE_FIELD = 'file';
    var PARENT_DIRECTORY = 'files/resumes/';

    // Validate here
    var fileFilter = function fileFilter (req, file, callback) {
        // allowed extensions .doc .docx .odt .pdf .txt
        var allowedMimeTypes = [
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.oasis.opendocument.text',
            'application/pdf',
            'text/plain'
        ];
        var validMimetype = allowedMimeTypes.some(function(mimetype) {
            return file.mimetype == mimetype;
        });

        if (!validMimetype) return callback(new Error('Resume is not a valid file format'));

        callback(null, true)
    };

    var fileOptions = {
        fileFilter: fileFilter,
        dest: 'tmp/',
        limits: {
            fileSize: MAX_FILE_SIZE
        }
    };
    var upload = multer(fileOptions).single(FILE_FIELD);

    upload(req, res, function(err) {
        if (err) return res.status(400).send({message: err.message});

        // We don't need a new file if req.body.resume has a value
        console.log(typeof req.body.resume);
        if (_.isEmpty(req.body.resume) && typeof req.file === 'undefined') {
            return res.status(400).send({message: 'Resume file is required'});
        }

        // Make sure that if there is a resume file but no new file, the resume exists in the file system.
        if (req.body.resume && typeof req.file === 'undefined') {
            fs.stat('client/' + req.body.resume, function(err, stats) {
                if (err) {
                    return res.status(400).send({message: 'Resume doesn\'t exist on file server'});
                } else {
                    return next();
                }
            })
        } else {
            // Let's add the file path at req.body.resume.
            // The idea is that if the save method on the model returns and error. Delete the file
            // in the tmp folder. Then return an error. If the model validates and is saved. Move the
            // file into the proper folder

            req.body.resume = PARENT_DIRECTORY + req.user._id + '/' + req.file.originalname;
            return next();
        }
    });
};

Метод контроллера обновления:

exports.update = function(req, res) {
    var crewListing = req.app.locals.crewListing;

    // Protect information
    delete req.body.author;
    delete req.body.__v;
    delete req.body._id;

    // Merge objects
    _.merge(crewListing, req.body);

    crewListing.save({runValidators: true}, function(err, result) {
        if (req.file) {
            if (err) {
                // Delete the req file
                fs.unlink(req.file.path, function() {
                    return res.status(400).send(validationErrorHandler(err,true));
                });
            } else {
                // Move the req file
                console.log(req.file);
                fs.move(req.file.path, 'client/' + crewListing.resume, {clobber: true}, function(err) {
                    if (err) return res.status(400).send({message: 'Unexpected error has occured'})
                    return res.json(result);
                });
            }
        } else {
            if (err) return res.status(400).send(validationErrorHandler(err, true));
            return res.json(result);
        }
    })
};

person Adam S    schedule 11.08.2016    source источник


Ответы (1)


Директива ng-required в поле файла может быть условной. Если текстовое поле резюме имеет значение, то поле файла не обязательно.

ng-required="!vm.profile.resume"
person Adam S    schedule 11.08.2016