在nginx中是否有一种方法可以创建一个简单的静态图像库,而不需要任何第三方工具?

13

我只是想能够一次分享多张图片的链接。

5个回答

17

最简单的方法是转换nginx的文件列表。您可以通过使nginx输出列表作为XML,然后使用XSLT进行转换来实现这一点。内置模块ngx_http_autoindex_module将执行前者,通常动态模块ngx_http_xslt_filter_module(也称为ngx_http_xslt_module)将执行后者。

首先,如果需要,请在nginx.conf中加载模块:

load_module "/usr/lib/nginx/modules/ngx_http_xslt_filter_module.so";

接着,在您的sites-available/website.com中添加一个位置,告诉nginx使用样式表gal.xslt来转换xml索引,并传递文件夹名称作为参数。

location ~ /gal/([A-z]+)/$ {
    autoindex on;
    autoindex_format xml;
    xslt_string_param title $1;
    xslt_stylesheet gal.xslt;
    try_files $uri/ =404;
}

最后,在/ etc / nginx中创建gal.xslt,其内容为:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" indent="yes" />
<xsl:template match="/">
    <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;</xsl:text>
    <html>
    <head>
        <title><xsl:value-of select="$title" /></title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <style>
        img, video {
            display: block;
            max-width: 20cm;
            max-height: 20cm;
            margin: 2mm;
            vertical-align: bottom;
            image-orientation: from-image;
        }
        @media all and (max-width: 20.4cm) {
            img {
                max-width: calc(100% - 4mm);
            }
        }
        body {
            margin: 0;
        }
        </style>
    </head>
    <body>
        <xsl:for-each select="list/file">
            <xsl:choose>
                <xsl:when test="contains(' mp4 webm mkv avi wmv flv ogv ', concat(' ', substring-after(., '.'), ' '))">
                    <video controls="" src="{.}" alt="{.}" title="{.}"/>
                </xsl:when>
                <xsl:otherwise>
                    <img src="{.}" alt="{.}" title="{.}"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </body>
    </html>
</xsl:template>
</xsl:stylesheet>

现在将一些图片放入/var/www/html/gal/foo中,重新启动nginx,导航到website.com/gal/foo,您将看到一个简单但可用和响应式的图像库。


这太棒了!谢谢。 - gerasalus
美观简洁!图片出现了404状态码。我不得不在Nginx 1.19上将try_files $uri/ =404;更改为try_files $uri $uri/ =404; - Lee Irvine

7

感谢@squirrel,这真的很简单却强大。

我调整了xslt - 下面是这个版本gal.xslt:

  • Displays tumbnails in a grid, four columns wide.
  • Resizes according to page size.
  • Each image is click-able, so you can see the full size image.

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" encoding="utf-8" indent="yes" />
    <xsl:template match="/">
    <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;</xsl:text>
    <html>
    <head>
        <title><xsl:value-of select="$title" /></title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <style>
        img {
             display: inline;
             width: 23%;    
             margin: 2mm;
             vertical-align: bottom;
        }
        @media all and (max-width: 20.4cm) {
            img {
                max-width: calc(100% - 4mm);
            }
        }
        body {
            margin: 0;
        }
        </style>
    </head>
    <body>
        <xsl:for-each select="list/file">
            <a href="{.}" title="click to enlarge">
                <img src="{.}" alt="{.}"/>
            </a>
       </xsl:for-each>
    </body>
    </html>
    </xsl:template>
    </xsl:stylesheet>
    
干杯,
Greg

1
做得不错,下一步是混合图像过滤器模块以在服务器端生成和缓存缩略图 ;) - miknik

2
我稍微调整了一下:fancybox、缩略图处理(使用预生成的缩略图在thumbs目录中)、能够下载所有图像作为浏览器生成的zip文件。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" indent="yes" />
<xsl:template match="/">
<xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;</xsl:text>
<html>
<head>
  <title><xsl:value-of select="$title" /></title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" integrity="sha256-Vzbj7sDDS/woiFS3uNKo8eIuni59rjyNGtXfstRzStA=" crossorigin="anonymous"/>
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" integrity="sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/jszip@3.1.5/dist/jszip.min.js" integrity="sha256-PZ/OvdXxEW1u3nuTAUCSjd4lyaoJ3UJpv/X11x2Gi5c=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js" integrity="sha256-xoh0y6ov0WULfXcLMoaA6nZfszdgI8w2CEJ/3k8NBIE=" crossorigin="anonymous"></script>
  <style>img { display: block; }</style>
</head>
<body>
<h1 style="text-align: center;"><xsl:value-of select="$title"/></h1>
<div style="border-bottom: 1px solid gray; margin-bottom: 1rem;"></div>
<div style="display: flex; flex-wrap: wrap; gap: 2px; justify-content: center;">
<xsl:for-each select="list/file">
  <a href="{.}" data-fancybox="gallery">
  <xsl:choose>
  <xsl:when test="count(/list/directory[text() = 'thumbs'])">
    <img loading="lazy" src="thumbs/{.}"/>
  </xsl:when>
  <xsl:otherwise>
    <img loading="lazy" src="{.}" height="200"/>
  </xsl:otherwise>
  </xsl:choose>
  </a>
</xsl:for-each>
</div>
<script>
async function downloadAll() {
  const zip = JSZip();
  const folder = zip.folder('<xsl:value-of select="$title" />');
  const files = [
    <xsl:for-each select="list/file">
     '<xsl:value-of select="." />',
    </xsl:for-each>
  ];
  for(const i in files) {
    const file = files[i];
    const resp = await fetch(file);
    folder.file(file, resp.blob());
    $.fancybox.animate($.fancybox.getInstance().SlideShow.$progress.show(),{scaleX: i/files.length}, 0.1);
  }
  const zipFile = await zip.generateAsync({type: 'blob'});
  saveAs(zipFile, '<xsl:value-of select="$title" />' + '.zip');
  $.fancybox.animate($.fancybox.getInstance().SlideShow.$progress.show(),{scaleX: 0}, 0.1); 
}

$('[data-fancybox="gallery"]').fancybox({
  buttons: [
    "zoom",
    "slideShow",
    "fullScreen",
    "download",
    "downloadAll",
    "close"
  ],
  btnTpl: {
    downloadAll:
      '<a class="fancybox-button fancybox-button--download" title="Download All" href="javascript:downloadAll()">' +
      '<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3M3 17V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z" style="fill:unset; stroke-width:2"/></svg>' +
      '</a>',
 },
});
$('[data-fancybox="gallery"]')[0].click();
</script>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

1

我还进行了一些微调,使用JS和CS准备生成配置文件。主要功能包括:

  • 图像...
    • 读取EXIF(通过exifr
    • 在Google地图上显示GPS
    • 查看全景照片(通过Photo Sphere Viewer
    • 可选自动图像缩略图及可选缓存
  • 视频(通过Plyr支持将SRT字幕自动转换为VTT格式
  • 其他文件(只能查看和下载)
  • 共享相册链接
  • 社交网络共享(通过shareon
  • 使用GLightbox作为灯箱
  • HTTP或HTTPS(支持Let's encrypt - 例如通过外部工具dehyhrated
  • 自定义相册标题/网站图标以及许多其他设置
  • 密码访问(通过HTTP基本身份验证)

您可以在https://github.com/forrest79/StaticNginxGallery上查看它。


0

@squirrel的精彩回答激发了我将所有内容打包到容器中以便于部署。 https://github.com/stuart23/image_server

说明在自述文件中 - 它非常简单:

docker build -t image_server .
docker run -p 8000:8000 -v /local/path/to/gallery:/var/www image_server

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接