我正在尝试提供我的 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 中执行此操作的最佳猜测。
对于
adapter-node
,建议的方法是将应用程序数据放置在项目根目录下的新文件夹中(即在 /src
和 /static
旁边)。然后您可以使用相对路径读取文件:fs.readFile('./my-app-data/foo.txt')
。
对于部署,您只需确保从项目根目录执行
node build
,因为这可以保证您在开发和生产期间拥有相同的工作目录。
static
文件夹works,但它并不意味着携带应用程序数据 - 该文件夹中的文件代表直接向用户提供服务的新路由,因此如果必须以任何方式保护生成的文件,则这是不可取的。即使它们是公共文件,它仍然模糊了应该是生产和源数据的内容:新的部署是否应该覆盖static
中的所有文件?如果您不小心,命名冲突可能意味着覆盖生产数据。
您可以使用
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'
选项结合使用,可以有效地将每个文件的内容嵌入到生成的代码中。 (这纯粹是服务器端,所以不用担心向客户端发送太多内容)
请注意,这当然意味着只有在构建期间存在的文件才能以这种方式提供服务。
正如@Stephane 建议的那样,将文件放在
statics
文件夹下。这样你就可以直接通过反向代理提供服务,比如Nginx
对于任何查看此代码的人
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: {} })
希望这能节省一些时间,我只花了几分钟调试:)