def parse_blob_info(field_storage):
if field_storage is None:<EOL><INDENT>return None<EOL><DEDENT>field_name = field_storage.name<EOL>def get_value(dct, name):<EOL><INDENT>value = dct.get(name, None)<EOL>if value is None:<EOL><INDENT>raise BlobInfoParseError(<EOL>'<STR_LIT>' % (field_name, name))<EOL><DEDENT>return value<EOL><DEDENT>filename = get_value(field_storage.disposition_options, '<STR_LIT:filename>')<EOL>blob_key_str = get_value(field_storage.type_options, '<STR_LIT>')<EOL>blob_key = BlobKey(blob_key_str)<EOL>upload_content = email.message_from_file(field_storage.file)<EOL>content_type = get_value(upload_content, '<STR_LIT>')<EOL>size = get_value(upload_content, '<STR_LIT>')<EOL>creation_string = get_value(upload_content, UPLOAD_INFO_CREATION_HEADER)<EOL>md5_hash_encoded = get_value(upload_content, '<STR_LIT>')<EOL>md5_hash = base64.urlsafe_b64decode(md5_hash_encoded)<EOL>try:<EOL><INDENT>size = int(size)<EOL><DEDENT>except (TypeError, ValueError):<EOL><INDENT>raise BlobInfoParseError(<EOL>'<STR_LIT>' % (size, field_name))<EOL><DEDENT>try:<EOL><INDENT>creation = blobstore._parse_creation(creation_string, field_name)<EOL><DEDENT>except blobstore._CreationFormatError as err:<EOL><INDENT>raise BlobInfoParseError(str(err))<EOL><DEDENT>return BlobInfo(id=blob_key_str,<EOL>content_type=content_type,<EOL>creation=creation,<EOL>filename=filename,<EOL>size=size,<EOL>md5_hash=md5_hash,<EOL>)<EOL>
Parse a BlobInfo record from file upload field_storage.

    Args:
      field_storage: cgi.FieldStorage that represents uploaded blob.

    Returns:
      BlobInfo record as parsed from the field-storage instance.
      None if there was no field_storage.

    Raises:
      BlobInfoParseError when provided field_storage does not contain enough
      information to construct a BlobInfo object.