如何 Return 来自 SvelteKit 端点的文件

How to Return File from SvelteKit Endpoint

我正在尝试提供我的 SvelteKit 应用程序生成的 PDF 文件并允许用户从端点下载它。

我的项目结构如下所示:

---------------------
/src/routes/downloads
---------------------
[file].ts
ABC.pdf
XYZ.pdf

我的 [file].ts 端点如下所示:

import fs from 'fs'

// ----- GET -----
export async function get({ params }){
  //console.log(params.file) -> ABC

  var pdf = fs.readFileSync('./src/routes/downloads/'+params.file+'.pdf')

  return{
    status:200,
    headers: {
      "Content-type" : "application/pdf",
      "Content-Disposition": "attachment; filename="+params.file+".pdf"
    },
    body: pdf
  }
}

然后当我点击 http://localhost:3000/downloads/ABC 时,名为 ABC.pdf 的 PDF 文件下载。

但是我的 readFileSync 路径不适用于生产环境。据我所知,没有 /src/routes 文件夹。

如何从 http://localhost:3000 url 提供我的文件?我尝试过的所有方法都会产生 404 并且无法找到该文件。我也愿意采用不同的方式来处理这种情况。这只是我对如何在 SvelteKit 中执行此操作的最佳猜测。

按照@Stephane 的建议,将您的文件放在statics 文件夹下。这样你就可以直接通过反向代理服务,比如 Nginx

您可以为此使用 import.meta.glob

export async function get({ params }){
  const file = `./${params.file}.pdf`;
  const pdfs = import.meta.glob(('./*.pdf', { as: 'raw' });
  const pdf = pdfs[file];

  return {
    status:200,
    headers: {
      "Content-type" : "application/pdf",
      "Content-Disposition": "attachment; filename="+params.file+".pdf"
    },
    body: pdf
  }
}

import.meta.glob 结合 as: 'raw' 选项将有效地 嵌入 每个文件的内容到您的结果代码中。 (这纯粹是服务器端,所以不用担心向客户端发送太多)

请注意,这当然意味着只有 在构建 期间存在的文件才能以这种方式提供。

对于 adapter-node,推荐的方法是将您的应用程序数据放在项目根目录下的一个新文件夹中(即在 /src/static 旁边) .然后您可以读取具有相对路径的文件:fs.readFile('./my-app-data/foo.txt').

对于部署,您只需确保从项目根目录执行 node build,因为这可以保证您在开发和生产期间拥有相同的工作目录。

static 文件夹 有效 ,但它并不意味着携带应用程序数据——此文件夹中的文件代表直接为用户提供的新路线,因此这如果必须以任何方式保护生成的文件,则不可取。即使它们是 public 文件,它仍然模糊了应该是生产和源数据的内容:新部署是否应该覆盖 static 中的所有文件?如果您不小心,命名冲突可能意味着覆盖生产数据。