如何从 SvelteKit 端点返回文件

问题描述 投票:0回答:4

我正在尝试提供我的 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
网址提供我的文件?我尝试过的所有操作都会产生
404
并且找不到该文件。我也愿意采用不同的方式来处理这种情况。这只是我对如何在 SvelteKit 中执行此操作的最佳猜测。

rest svelte fs sveltekit
4个回答
10
投票

对于

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

对于部署,您只需确保从项目根目录执行

node build
,因为这可以保证您在开发和生产期间拥有相同的工作目录。

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


1
投票

您可以使用

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'
选项结合使用,可以有效地将每个文件的内容嵌入到生成的代码中。 (这纯粹是服务器端,所以不用担心向客户端发送太多内容)

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


0
投票

正如@Stephane 建议的那样,将文件放在

statics
文件夹下。这样你就可以直接通过反向代理提供服务,比如Nginx


0
投票

对于任何查看此代码的人

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
  }
}

并想知道为什么它不起作用......

这不再是 SvelteKit 中的做法了。 目前您需要返回一个 Response 对象,如下所示:

return new Response(body, { status: 200, headers: {} })

希望这能节省一些时间,我只花了几分钟调试:)

© www.soinside.com 2019 - 2024. All rights reserved.