public function storeFile($filename, array $extra = [], array $options = [])
    {
        $this->createChunksIndex();

        $record = $extra;
        if (is_string($filename)) {
            $record += [
                'md5' => md5_file($filename),
                'length' => filesize($filename),
                'filename' => $filename,
            ];

            $handle = fopen($filename, 'r');
            if (! $handle) {
                throw new MongoGridFSException('could not open file: ' . $filename);
            }
        } elseif (! is_resource($filename)) {
            throw new \Exception('first argument must be a string or stream resource');
        } else {
            $handle = $filename;
        }

        $md5 = null;
        try {
            $file = $this->insertFile($record, $options);
        } catch (MongoException $e) {
            throw new MongoGridFSException('Could not store file: ' . $e->getMessage(), $e->getCode(), $e);
        }

        try {
            $length = $this->insertChunksFromFile($handle, $file, $md5);
        } catch (MongoException $e) {
            $this->delete($file['_id']);
            throw new MongoGridFSException('Could not store file: ' . $e->getMessage(), $e->getCode(), $e);
        }


        // Add length and MD5 if they were not present before
        $update = [];
        if (! isset($record['length'])) {
            $update['length'] = $length;
        }
        if (! isset($record['md5'])) {
            try {
                $update['md5'] = $md5;
            } catch (MongoException $e) {
                throw new MongoGridFSException('Could not store file: ' . $e->getMessage(), $e->getCode(), $e);
            }
        }

        if (count($update)) {
            try {
                $result = $this->update(['_id' => $file['_id']], ['$set' => $update]);
                if (! $this->isOKResult($result)) {
                    throw new MongoGridFSException('Could not store file');
                }
            } catch (MongoException $e) {
                $this->delete($file['_id']);
                throw new MongoGridFSException('Could not store file: ' . $e->getMessage(), $e->getCode(), $e);
            }
        }

        return $file['_id'];
    }