受密码保护的相册 PHP/MySQL 服务器负载

Password Protected Photo Album PHP/MySQL Server Load

我正在制作一个网站,允许用户共享带有缩略图的可搜索相册,这些相册将受密码保护。我的计划是验证密码并将 PHP 会话设置为相册的 ID。然后当用户加载相册时,服务器将提供所有图片引用 ID 的列表。使用 ajax 调用,客户端将通过 GET 请求请求所有符合请求条件的图片,包括照片 ID。然后使用 PHP 我将检查当前会话是否已获得该相册的授权,然后 MySQL 查询图片位置,然后 return 图片。

既然您已经阅读了我的设计思路,我担心如果相册足够大,服务器负载会迅速增加,因为每个缩略图都需要单独的请求和 MySQL 查询。我还没有实施和测试,但想知道我是否应该重新开始我的设计。

有没有更好的方法来解决这个问题?

简单的 PHP 脚本和 MySQL 查询的加载量会很大吗?

没有理由要求每个单独的缩略图都需要单独的请求甚至单独的查询。您可以在单个请求和单个查询中同时执行。

假设您的缩略图在您的数据库中存储为 URLs 并与相册 ID 相关联。这意味着像这样的单个查询可以检索相册的所有缩略图。

SELECT
    thumbnails.url
FROM
    thumbnails
JOIN
    albums ON thumbnails.album_id = albums.id
WHERE
    thumbnails.album_id = 1

现在您可以简单地对这些结果进行分页以减少服务器负载。假设您希望每页最多加载 50 个缩略图。

SELECT
    thumbnails.url
FROM
    thumbnails
JOIN
    albums ON thumbnails.album_id = albums.id
WHERE
    thumbnails.album_id = 1
LIMIT
    0,50

然后您可以对下一页执行 LIMIT 50,50,然后对下一页执行 LIMIT 100,50 等等。

您可以在 AJAX 响应中将缩略图结果列表作为 JSON 发送回客户端,客户端可以通过 javascript 将每个缩略图加载到页面上。

为什么您可能认为这行不通

如果您的想法是您需要对这些缩略图进行单独请求,因为您希望 PHP 验证用户是否有权查看相册,那么您太难解决了两个问题同时出现。

获取缩略图URLs给客户端的问题是一步到位。这很容易通过检查用户的 $_SESSION 来实现,就像您计划做的那样,并确保在您执行查询之前他们可以访问 album_id 并将他们发回 JSON 结果。

下一步是限制对相册及其缩略图的访问。不幸的是,您必须在 HTTP/1.1 中为此单独提出请求。没有办法解决这个问题,但是这仍然不需要很昂贵。

您只需使用 PHP 来验证 $_SESSION 变量是否包含所需的 album_id 检查并依靠您的网络服务器的 Sendfile capabilities 来处理实际的服务图片给客户。

所以 PHP 只处理验证用户是否有权查看图像的部分。您的网络服务器会处理提供服务的部分。此请求中没有要执行的数据库查询。所以这不是数据库负载问题。

在 PHP 中,使用 Apache httpd(作为示例),这会像这样工作。

if (isset($_SESSION['album_id']) && $_SESSION['album_id'] === $_GET['album_id']) {
    // User has access
    header("X-Sendfile: " . $pathToImageOnFileSystem);
    exit;
} else {
    // User is not authorized :/
    echo "Unauthorized access!";
}

这样做是将响应 header 发送回您的网络服务器,让它知道“您需要将 $pathToImageOnFileSystem 中指定的文件提供给客户端”。 PHP 的角色在将 header 发送回您的网络服务器后结束。网络服务器然后完成其余的工作。所以PHP没有被捆绑

棘手的部分是确保您以一种将 URL 指向图像 ID 的方式定义您的网络服务器重写规则,您可以在其中将其映射到文件系统上的文件。例如,您可以将图像存储在 /home/myapp/images/{album_id}/{image_id} 中,以便像 http://www.example.com/images/1/1 这样的 URL 被您的网络服务器读取并发送到 PHP 然后 PHP 可以确定$pathToImageOnFileSystem 应该是 /home/myapp/images/1/1。 PHP 通过检查 albumb_id 是否在 $_SESSION 中已经知道用户是否具有访问权限,因为它会在之前的身份验证中存储。

当然,还要确保文件在您的网络服务器提供时发回正确的 MIME 类型和文件扩展名。所以你可能想将 /home/myapp/images/{album_id}/{image_id} 映射到 /home/myapp/images/{album_id}/{image_id}.* 或类似的东西。