public function generatePreSignedUrl($bucketName, $key, $options = array())
    {
        list(
            $config,
            $headers,
            $params,
            $signOptions
        ) = $this->parseOptions(
            $options,
            BosOptions::CONFIG,
            BosOptions::HEADERS,
            BosOptions::PARAMS,
            BosOptions::SIGN_OPTIONS
        );
        if(is_null($config)) {
            $config = $this->config;
        } else {
            $config = array_merge($this->config, $config);
        }
        if(is_null($params)) {
            $params = array();
        }
        if(is_null($headers)) {
            $headers = array();
        }

        $path = $this->getPath($bucketName, $key);

        list($hostUrl, $hostHeader) =
            HttpUtils::parseEndpointFromConfig($config);
        $headers[HttpHeaders::HOST] = $hostHeader;

        $auth = $this->signer->sign(
            $config[BceClientConfigOptions::CREDENTIALS],
            HttpMethod::GET,
            $path,
            $headers,
            $params,
            $signOptions
        );
        $params['authorization'] = $auth;

        $url = $hostUrl . HttpUtils::urlEncodeExceptSlash($path);
        $queryString = HttpUtils::getCanonicalQueryString($params, false);
        if ($queryString !== '') {
            $url .= "?$queryString";
        }
        return $url;
    }