网页 Base64 编码的 Image

728 阅读3分钟

网页 Base64 编码的 Image

可以遗憾,但不要后悔。 

我们留在这里,从来不是身不由己。 

——— 而是选择在这里经历生活

概述

图片转换为 base64 编码常见的应用场景:

将网页中的一些图片转换为 base64 编码可以实现网页图片在低网速的情况下先于内容加载和减少 HTTP 的请求次数来减少对网站服务器的负担。

总之,这样做的好处:

  1. 减少 HTTP 请求
  2. 提前加载应用的图片

其中,data 类型的 url image 相关如下:

data:image/gif;base64,base64编码的gif图片数据
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据
data:image/svg+xml;base64,base64编码的svg图片数据

某些网站打开 inspector 定位图片的截图:

inspector.png

使用 Python 进行图片 base64 编码转换

说明

这个类是一个图片转换工具,它提供了将图片文件转换为 base64 编码字符串的方法,以及将 base64 编码的图片字符串转换回图片文件的方法。

使用该类,你可以将图片文件转换为一个经过 base64 编码的字符串,该字符串可以直接嵌入到 HTMLCSS 等代码中,从而减少 HTTP 请求,提高页面加载速度。还可以使用该类将 base64 编码的图片字符串转换回图片文件,以便进行其他操作,例如存储到本地等。

该类支持多种常见的图片格式,包括 JPEGPNGGIFICOSVG,并能自动识别图片的 MIME 类型。当然,也可以自定义 MIME 类型,以便支持更多的图片格式。

使用该类时,需要提供图片文件的绝对路径或 base64 编码的字符串,转换成功后,将返回 base64 编码的字符串或图片文件的绝对路径。如果提供的文件不存在或不是一个合法的图片文件,或者提供的字符串不是一个合法的 base64 编码的图片,将抛出 ValueError 异常。

代码

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import base64
import os
import re
import uuid


class ImageConverter:
    """Converts image files to base64 format and vice versa."""

    SUPPORTED_IMAGE_TYPES = ('.jpg', '.jpeg', '.png', '.gif', '.ico', '.svg')
    MIME_TYPES = {
        '.jpg': 'image/jpeg',
        '.jpeg': 'image/jpeg',
        '.png': 'image/png',
        '.gif': 'image/gif',
        '.ico': 'image/x-icon',
        '.svg': 'image/svg+xml'
    }

    @staticmethod
    def encode(file_path: str) -> str:
        """Converts an image file to a base64 string.

        Args:
            file_path (str): The absolute path to the image file.

        Returns:
            str: The base64-encoded string representation of the image.

        Raises:
            ValueError: If the file at the specified file path does not exist or is not a valid image file.
        """
        if not os.path.exists(file_path):
            raise ValueError(f"File not found: {file_path}")

        file_ext = os.path.splitext(file_path)[1].lower()
        if file_ext not in ImageConverter.SUPPORTED_IMAGE_TYPES:
            raise ValueError(f"Unsupported image file type: {file_ext}")

        with open(file_path, "rb") as file:
            encoded_string = base64.b64encode(file.read()).decode()

        mime_type = ImageConverter.MIME_TYPES.get(file_ext, 'application/octet-stream')
        return f"data:{mime_type};base64,{encoded_string}"

    @staticmethod
    def decode(data: str) -> str:
        """Converts a base64-encoded string to an image file.

        Args:
            data (str): The base64-encoded string representation of the image.

        Returns:
            str: The absolute path to the decoded image file.

        Raises:
            ValueError: If the provided string is not a valid base64-encoded image.
        """
        regex = re.compile(r'^data:(?P<mime_type>.*?);base64,(?P<data>.*)$')
        match = regex.match(data)
        if not match:
            raise ValueError('Invalid base64-encoded image')

        mime_type = match.group('mime_type')
        data = match.group('data')

        mime_ext = mime_type.split('/')[-1]
        file_ext = f".{mime_ext}" if mime_ext != 'x-icon' else '.ico'
        if file_ext not in ImageConverter.MIME_TYPES:
            raise ValueError(f"Unsupported image MIME type: {mime_type}")

        image_data = base64.b64decode(data)
        file_path = f"{uuid.uuid4()}{file_ext}"
        with open(file_path, "wb") as file:
            file.write(image_data)

        return file_path


if __name__ == '__main__':
    # Example usage
    encoded_string = ImageConverter.encode("example.jpg")
    print(encoded_string)

    decoded_file_path = ImageConverter.decode(encoded_string)
    print(decoded_file_path)

输出

# 图片转base64字符串
data:image/jpg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDA...

# base64字符串转图片
70d7bcf3-195f-4ba1-9c79-cf463f9a9dd9.png