【问题标题】:How to make seadragon js work with AWS S3 presigned URL如何使 seadragon js 与 AWS S3 预签名 URL 一起使用
【发布时间】:2021-06-08 20:41:37
【问题描述】:

我正在尝试让 openseadragon js 处理存储在我的 AWS S3 存储桶中的图像。这些文件是私有的,我不确定如何引用包含我所有金字塔图像的文件夹。在 tilesource-custom documentation 中,他们使用了:

OpenSeadragon({
    id:            "example-custom-tilesource",
    prefixUrl:     "/openseadragon/images/",
    navigatorSizeRatio: 0.25,
    wrapHorizontal:     true,
    tileSources:   {
        height: 512*256,
        width:  512*256,
        tileSize: 256,
        minLevel: 8,
        getTileUrl: function( level, x, y ){
            return "http://s3.amazonaws.com/com.modestmaps.bluemarble/" +
                    (level-8) + "-r" + y + "-c" + x + ".jpg";
        }
    }
});

我不确定 getTileUrl 中的 function(level, x, y) 是如何工作的。我假设它迭代到某个点。任何关于它如何工作的解释都会有帮助。所以基于这个例子,我尝试了以下方法:

const s3 = new AWS.S3();

const s3_bucket_url_js = function($key) {

    s3.getSignedUrl('getObject', {
            Bucket: "g-deliverables",
            Expires: 60*30,
            Key: $key,
    }, function (err, url) {
        if (err) {
         console.log(err);
     } else {
         console.log(typeof url);
         return url;

     }

    });
}


OpenSeadragon({
    id:            "openseadragon1",
    prefixUrl:     "/GTSS/assets/buttons",
        showNavigator: false,
    tileSources:   {
        type: 'zoomifytileservice',
        height: 3600,
        width:  2700,
        tileSize: 256,
            getTileUrl: function( level, x, y ){
            var url_s = "whatever/pyr/some#/01_VISUAL/TileGroup0/" +level + "-" + x + "-" + y + ".jpg";
            return s3_bucket_url_js(url_s);
        }
    }
});

我为 JS 使用了 AWS sdk 版本 2。我创建了一个将存储桶键作为参数的函数,然后将这个名为 s3_bucket_url_js 的函数放入 getTileUrl 函数(级别、x、y)中。因为我不知道 function(level, x, y) 是如何工作的,所以我假设它迭代到了 min-level,所以我让它创建了我的 jpg 文件名,它遵循三位数的命名约定:0-0-0。 jpg、1-0-0.jpg、1-1-0.jpg 等。我认为将整个键值放入我的 s3_bucket_url 函数中,以创建一个预签名的 url,我希望它能够成功呈现。当然没有。

我在s3 bucket中的文件夹结构如下:

folder structure s3 bucket

当我将文件存储在我的 ec2 上时,我只是引用了 tilesUrl: 'gtss/pyr/103/01_VISUAL/ 而不是 getTileUrl,它在编译所有图像时工作得很好。但我无法引用 s3 存储桶上的文件夹,因为它是私有的。

最后,我在 html 中添加了 div 标签,供 openseadragon 地图显示。

<div id="openseadragon1" style="width: 800px; height: 600px;"></div>

快速更新:我查看了我正在使用的 openseadragon.min.js 文件,并相信我找到了返回每个金字塔图像路径的函数 getTileUrl。如下:

    _calculateAbsoluteTileNumber: function(e, t, i) {
            var n = 0;
            var o = {};
            for (var r = 0; r < e; r++) n += (o = this.gridSize[r]).x * o.y;
            return n += (o = this.gridSize[e]).x * i + t
        },
        supports: function(e, t) {
            return e.type && "zoomifytileservice" == e.type
        },
        configure: function(e, t) {
            return e
        },
        getTileUrl: function(e, t, i) {
            var n;
            var o = this._calculateAbsoluteTileNumber(e, t, i);
            n = Math.floor(o / 256);
            return this.tilesUrl + "TileGroup" + n + "/" + e + "-" + t + "-" + i + ".jpg"
        }

现在我正在考虑尝试在 getTileUrl 方法中使用我的 s3_bucket_url_js 函数并返回 s3_bucket_url_js(this.tilesUrl + "TileGroup" + n+ "/" + e + "-" + t + "-" + i + ".jpg"

之前有评论说从后端调用预签名的 url 并将其传递给前端。我该怎么做才能使用 openseadragon.min.js 文件中的 s3_bucket_url_js()?

这是代码sn-p的未缩小版:

  //private
        _calculateAbsoluteTileNumber: function(level, x, y) {
            var num = 0;
            var size = {};

            //Sum up all tiles below the level we want the number of tiles
            for (var z = 0; z < level; z++) {
                size = this.gridSize[z];
                num += size.x * size.y;
            }
            //Add the tiles of the level
            size = this.gridSize[level];
            num += size.x * y + x;
            return num;
        },

        /**
         * Determine if the data and/or url imply the image service is supported by
         * this tile source.
         * @function
         * @param {Object|Array} data
         * @param {String} optional - url
         */
        supports: function(data, url) {
            return (data.type && "zoomifytileservice" == data.type);
        },

        /**
         *
         * @function
         * @param {Object} data - the raw configuration
         * @param {String} url - the url the data was retrieved from if any.
         * @return {Object} options - A dictionary of keyword arguments sufficient
         *      to configure this tile sources constructor.
         */
        configure: function(data, url) {
            return data;
        },

        /**
         * @function
         * @param {Number} level
         * @param {Number} x
         * @param {Number} y
         */
        getTileUrl: function(level, x, y) {
            //console.log(level);
            var result = 0;
            var num = this._calculateAbsoluteTileNumber(level, x, y);
            result = Math.floor(num / 256);
            return this.tilesUrl + 'TileGroup' + result + '/' + level + '-' + x + '-' + y + '.jpg';

        }

【问题讨论】:

  • 您需要后端生成预签名 URL 并将其传递给前端,否则您的 AWS 密钥和秘密将被泄露。
  • 好的,但看起来我必须在 openseadragon 创建每个金字塔图像的路径后创建预签名 URL。我查看了 openseadragon.min.js 的源代码,它看起来像这样: getTileUrl: function(e, t, i) { var n; var o = this._calculateAbsoluteTileNumber(e, t, i); n = Math.floor(o / 256);返回 this.tilesUrl + "TileGroup" + n + "/" + e + "-" + t + "-" + i + ".jpg" } })(代码结束 sn-p)。我正在尝试在 this.tilesUrl + 等的返回上添加我的 s3_bucket_url_js 函数。我该怎么做?

标签: javascript amazon-s3 pre-signed-url openseadragon


【解决方案1】:

到目前为止,我们已经弄清楚了如何通过 js 浏览器输出 s3 预签名的 url。我们使用 aws cognito 身份池 id 代替 aws 秘密访问密钥,以允许我们在浏览器中使用 aws sdk js。通过修改我们使用的 openseadragon.min.js 文件,我们能够为图片放置预签名的 url。在第 5370 行附近有一个 getTileUrl 函数,用于编译缩放金字塔的文件夹路径:

  getTileUrl: function(e, t, i) {
        var n;
        var o = this._calculateAbsoluteTileNumber(e, t, i);
        n = Math.floor(o / 256);
        var url = this.tilesUrl + "TileGroup" + n + "/" + e + "-" + t + "-" + i + ".jpg";
        return s3_bucket_url_js(url);


    }

在最后一条语句中,我们在函数中放置了一个 return(位于我们放置地图 div 的同一个文件中),它返回一个可以编译的预签名 url。如果您注意到 var url = this.titleUrl 等。this.tilesUrl 位于 OpenSeadragon() 对象中:

var viewer = OpenSeadragon({
                  id:            "openseadragon1",
                  prefixUrl:     "assets/buttons/",
                  showNavigator: false,
tileSources:   {
          type: 'zoomifytileservice',
          height: 3600,
          width:  3600,
          tileSize: 256,
          tilesUrl: 'whatever/pyr/our path up to TileGroup#/'});

            

这是我们使用的 s3 函数(另请注意,我们为浏览器使用了 aws sdk 版本 2)。至少对我们来说,异步调用 s3.getSignedUrl() 是行不通的,所以我们不得不使用如下所示的同步方式:

   AWS.config.region = 'us-east-1';
   AWS.config.credentials = new AWS.CognitoIdentityCredentials({IdentityPoolId: 'your own identity pool' });
   const s3 = new AWS.S3();
   function s3_bucket_url_js(key) {
       var params = {Bucket: 'bucket name', Key: key, Expires:1000};
       var s3_presigned = s3.getSignedUrl('getObject', params);
       return s3_presigned;
       }

另请注意,身份池适用于未经身份验证的用户。我们向附加到身份池的角色添加了 s3 只读访问 IAM 策略。在我们向公众开放的 s3 存储桶中,我们添加了 CORS 政策:

[
{
    "AllowedHeaders": [
        "*"
    ],
    "AllowedMethods": [
        "GET"
    ],
    "AllowedOrigins": [
        "your site"
    ],
    "ExposeHeaders": [
        "Content-Type",
        "X-Amz-Date",
        "Authorization",
        "X-Api-Key",
        "X-Amz-Security-Token"
    ]
}

]

现在,我们在编译时遇到了一些问题。使用我们的密钥,OpenSeaDragon 成功编译了所有图像,但是使用 Identity Pool Id,金字塔的前 2 层没有编译并返回一个非预签名的 url https://s3.amazonaws.com/ 并且 chrome 正在发送 CORB 错误(可能是因为网址不是图片)。我相信这与浏览器为身份池 ID 发送的请求有关,但我们仍在尝试找出解决方法。

【讨论】:

    猜你喜欢
    • 2020-07-27
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多