def send_blob()

in src/google/appengine/ext/blobstore/blobstore.py [0:0]


  def send_blob(self,
                environ,
                blob_key_or_info,
                content_type=None,
                save_as=None,
                start=None,
                end=None,
                **kwargs):
    """Send a blob-response based on a blob_key.

    Returns the correct response headers for serving a blob. If BlobInfo
    is provided and no content_type specified, will set request content type
    to BlobInfo's content type.

    Args:
      environ: a WSGI dict describing the HTTP request (See PEP 333).
      blob_key_or_info: BlobKey or BlobInfo record to serve.
      content_type: Content-type header to override when known. If not set,
        this header is not included in the returned headers.
        Web frameworks might set the 'content-type' header to a default type,
        which prevents GAE from setting a guessed 'content-type'.
        This behavior can be bypassed by setting headers['content-type'] to None
        or an empty string explicitly after this function call.
      save_as: If True, and BlobInfo record is provided, use BlobInfos
        filename to save-as.  If string is provided, use string as filename.
        If None or False, do not send as attachment.
      start: Start index of content-range to send.
      end: End index of content-range to send.  End index is inclusive.
      **kwargs:
        The `use_range` keyworded argument provides content range from the
        requests' Range header.

    Raises:
      ValueError on invalid save_as parameter.

    Returns:
      headers: a `dict` containing response headers

    """
    if set(kwargs) - _SEND_BLOB_PARAMETERS:
      invalid_keywords = []
      for keyword in kwargs:
        if keyword not in _SEND_BLOB_PARAMETERS:
          invalid_keywords.append(keyword)
      if len(invalid_keywords) == 1:
        raise TypeError('send_blob got unexpected keyword argument %s.'
                        % invalid_keywords[0])
      else:
        raise TypeError('send_blob got unexpected keyword arguments: %s'
                        % sorted(invalid_keywords))


    use_range = kwargs.get('use_range', self.__use_range_unset)
    use_range_set = use_range is not self.__use_range_unset

    headers = {}
    range_header = _check_ranges(start, end, use_range_set, use_range,
                                 environ.get('HTTP_RANGE'))

    if range_header is not None:
      headers[BLOB_RANGE_HEADER] = range_header

    if isinstance(blob_key_or_info, BlobInfo):
      blob_key = blob_key_or_info.key()
      blob_info = blob_key_or_info
    elif isinstance(blob_key_or_info, str) and blob_key_or_info.startswith(
        '/gs/'):
      blob_key = create_gs_key(blob_key_or_info)
      blob_info = None
    else:
      blob_key = blob_key_or_info
      blob_info = None

    headers[BLOB_KEY_HEADER] = str(blob_key)

    if content_type:
      if isinstance(content_type, six.text_type):
        content_type = content_type.encode('utf-8')
      headers['Content-Type'] = content_type

    def send_attachment(filename):
      if isinstance(filename, six.text_type):
        filename_utf8 = filename.encode('utf-8')
        headers['Content-Disposition'] = (
            _CONTENT_DISPOSITION_FORMAT_UTF8 %
            (filename_utf8, urllib.parse.quote(filename_utf8).encode('utf-8')))
      else:
        headers['Content-Disposition'] = (
            _CONTENT_DISPOSITION_FORMAT % filename)

    if save_as:
      if isinstance(save_as, (bytes, six.text_type)):
        send_attachment(save_as)
      elif blob_info and save_as is True:
        send_attachment(blob_info.filename)
      else:
        if not blob_info:
          raise ValueError('Expected BlobInfo value for blob_key_or_info.')
        else:
          raise ValueError('Unexpected value for save_as.')

    return headers