docs: function getObject(params, callback) {
      var reqParams = {};
  
      reqParams['response-content-type'] = params['ResponseContentType'];
      reqParams['response-content-language'] = params['ResponseContentLanguage'];
      reqParams['response-expires'] = params['ResponseExpires'];
      reqParams['response-cache-control'] = params['ResponseCacheControl'];
      reqParams['response-content-disposition'] = params['ResponseContentDisposition'];
      reqParams['response-content-encoding'] = params['ResponseContentEncoding'];
  
      var BodyType;
  
      var self = this;
      var outputStream = params.Output;
      if (outputStream && typeof outputStream === 'string') {
          outputStream = fs.createWriteStream(outputStream);
          BodyType = 'stream';
      } else if (outputStream && typeof outputStream.pipe === 'function') {
          BodyType = 'stream';
      } else {
          BodyType = 'buffer';
      }
  
      var onProgress = params.onProgress;
      var onDownloadProgress = (function () {
          var time0 = Date.now();
          var size0 = 0;
          var FinishSize = 0;
          var FileSize = 0;
          var progressTimer;
          var update = function () {
              progressTimer = 0;
              if (onProgress && (typeof onProgress === 'function')) {
                  var time1 = Date.now();
                  var speed = parseInt((FinishSize - size0) / ((time1 - time0) / 1000) * 100) / 100 || 0;
                  var percent = parseInt(FinishSize / FileSize * 100) / 100 || 0;
                  time0 = time1;
                  size0 = FinishSize;
                  try {
                      onProgress({
                          loaded: FinishSize,
                          total: FileSize,
                          speed: speed,
                          percent: percent
                      });
                  } catch (e) {
                  }
              }
          };
          return function (info, immediately) {
              if (info && info.loaded) {
                  FinishSize = info.loaded;
                  FileSize = info.total;
              }
              if (immediately) {
                  clearTimeout(progressTimer);
                  update();
              } else {
                  if (progressTimer) return;
                  progressTimer = setTimeout(update, self.options.ProgressInterval || 1000);
              }
          };
      })();
  
      // 如果用户自己传入了 output
      submitRequest.call(this, {
          Action: 'name/cos:GetObject',
          method: 'GET',
          Bucket: params.Bucket,
          Region: params.Region,
          Key: params.Key,
          VersionId: params.VersionId,
          headers: params.Headers,
          qs: reqParams,
          rawBody: true,
          outputStream: outputStream,
          onDownloadProgress: onDownloadProgress,
      }, function (err, data) {
          onDownloadProgress(null, true);
          if (err) {
              var statusCode = err.statusCode;
              if (params.Headers['If-Modified-Since'] && statusCode && statusCode === 304) {
                  return callback(null, {
                      NotModified: true
                  });
              }
              return callback(err);
          }
          var result = {};
          if (data.body) {
              if (BodyType === 'buffer') {
                  result.Body = Buffer.from(data.body);
              } else if (BodyType === 'string') {
                  result.Body = data.body;
              }
          }
          if (data.headers && data.headers.etag) {
              result.ETag = data.headers && data.headers.etag;
          }
          util.extend(result, {
              statusCode: data.statusCode,
              headers: data.headers,
          });
          callback(null, result);
      });
  
  }