NodeJS NextJs中包含凭据的图像

p1iqtdky  于 2023-06-29  发布在  Node.js
关注(0)|答案(2)|浏览(92)

我想使用Webp格式的用户上传的图像,以减少带宽的使用,但我真的不知道如何与授权需要它。
我想限制访问和控制谁可以看到用户的图像,我需要传递一个令牌给我的API。问题是,如果这样做,共享图像的URL可能会导致没有凭据的人看到图片:

<img src={`${urlApi}/images/${imageId}/${token}`}/>

我看过how to set header for image tag,但我不知道如何使用NextJs(),因为内置加载器的本质是返回一个URL,并且会面临类似的凭据问题
有什么方法可以做到这一点?有什么建议吗?
)此外,从我所看到的和控制台的警告,我下一个不喜欢使用img标签

a8jjtwal

a8jjtwal1#

您可以通过几种方式来完成此操作,如果令牌是基于用户的登录状态添加的,则可能不需要令牌。
方法1:使用自定义Express服务器承载应用程序。将图像的路由处理程序放在nextjs处理程序之前,并在返回图像之前验证令牌或会话。
方法2:将你的nextjs应用放在nginx或apache后面,并将/images文件夹代理给一个验证令牌的应用(由你的nextjs应用中的私钥签名的JWT?)和proxy /到nextjs应用程序。
在任何情况下,添加缓存控制头,以便图像不被缓存,并且只有在会话有效时才能被检索。请注意,这是一个最好的努力,因为一旦你释放了图像,一旦你没有实际控制它。
Cache-Control: no-store, no-cache, max-age=0, must-revalidate, proxy-revalidate
注意Next/loader是一种操作为给定屏幕大小提供哪个公共图像url的方法。您可以使用自定义加载器来添加令牌,但除此之外,它对此用例没有实用程序。

2ledvvac

2ledvvac2#

我找到了一个解决我自己问题的方法,它可能有点过度设计,但它工作得很好海事组织。
所以我做了一个自定义的Image标签,可以这样调用:

<ProfileImage urlAPI={urlAPI} url={`/profile/${pictureId}`} token={token}/>

它是这样工作的:

import React, {useState, useEffect} from 'react';
import Image from 'next/image'
export default function ProfileImage({urlAPI, url, token}) {

    const [image, setImage] = useState(false);

    useEffect(() => {
        (async () => {
            //Get if url already exists in local storage
            let cached = window.localStorage.getItem(url);
            if(cached){
                setImage(cached);
            //If not, get it from API
            } else {
                const response = await fetch(urlAPI+url, {
                    headers: {
                        'Method': 'GET',
                        'Authorization': `${token}`
                    }
                });
                //Extract image from response body
                let base64Image = await response.json();
                let imageObject = await fetch(`data:image/webp;base64,${base64Image}`);
                imageObject = await imageObject.blob();

                //Create an Url that stores the image
                const objectURL = URL.createObjectURL(imageObject);

                //Save in local storage and component state
                setImage(objectURL);
                window.localStorage.setItem(url, objectURL);
            }
        })();
       () => {
         // clear memory if needed
         URL.revokeObjectURL(image);
         window.localStorage.removeItem(src);
       }
    }, [])

    return (
        <>
        {   image ?
            <Image src={image} alt="profile" className="rounded-full" width={90} height={90}/>
            :
            <div className=""></div>
        }
        </>
    )
}

我不知道的是,浏览器可以随时生成url来存储和缓存图像,所以我使用了这个功能,因为组件一直在向API请求图像,并在每次渲染组件时重新创建本地url。
我将升级此组件并使缓存失效。

相关问题