获取typescript NextJS中桶对象的AWS S3预签名URL,以便浏览器端可以使用@aws-sdk/S3 Client下载文件

ego6inou  于 2022-11-23  发布在  TypeScript
关注(0)|答案(1)|浏览(198)

这是使用的S3 Client的v3。所有现有的例子,我可以找到使用旧的aws-sdk包。我需要客户端(浏览器)从S3下载文件而不从后端泄露密钥。据我所知,这是正确的方法。到目前为止,我已经使用了https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_s3_request_presigner.html文档中的const presigned = await signer.presign(request);,但我不知道如何构造request。有人能提供建议吗?

nlejzf6q

nlejzf6q1#

页面/api/文件.ts:

import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { NextApiRequest, NextApiResponse } from "next";

export interface GetFileProps {
  url: string;
}

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<GetFileProps>,
) {
  const s3client = new S3Client({
    region: "region",
    credentials: {
      accessKeyId: "",
      secretAccessKey: "",
    },
  });

  const command = new GetObjectCommand({
    Bucket: "bucketName",
    Key: req.query.path as string,
  });

  const url = await getSignedUrl(s3client, command, { expiresIn: 900 });
  res.status(200).json({ url });
}

然后,前端可以使用该URL:

const aRef = React.useRef<any>();

  const getUrlAndDownload = React.useCallback((path: string) => {
    from(fetch(`http://localhost:3000/api/file?path=${path}`))
      .pipe(
        mergeMap(response => {
          return response.json();
        }),
        mergeMap((res: GetFileProps) => {
          aRef.current.href = res.url;
          aRef.current.click();
          return EMPTY;
        }),
        catchError(err => {
          console.log("Error fetching download URL", err);
          return err;
        }),
      )
      .subscribe();
  }, []);

而在tsx中:

<a ref={aRef} />

并且可以从一个onClick调用getUrlAndDownload,其中包含文件的路径。

相关问题