没有这样的文件或目录(os 错误 2),在 oak 中渲染 public 文件的统计信息

No such file or directory (os error 2), stat for rendering public files in oak

我第一次尝试 Deno (v1.16.4) 与 Oak (v10) 和 ejs。 tailwind 文件只是一个常规的 CSS 文件,因此无需安装。我在服务静态 CSS 文件时卡住了。我一定是忽略了什么。

当我转到 localhost:8080/tailwind.css 时,它会显示文件内容,但是当我转到 localhost:8080/admin 时,它不会显示 No such file or directory (os error 2), stat '/Users/XXXXXXXX/Documents/projectNameHere/public/admin'。我已尝试调整 root 并删除“/public”,但现在找不到 tailwind 文件或 html 文件。

但是,它似乎不是 ejs 文件,因为删除第一个 app.use() 将显示管理页面(当然没有样式)。所以这些都有效。

这是应用入口的 app.js

import { Application } from "https://deno.land/x/oak/mod.ts";
import { route_home } from "./routes/home.js";
import { route_login } from "./routes/login.js";
import { route_admin } from "./routes/admin.js";
import { route_project } from "./routes/projectSingle.js";
import { route_about } from "./routes/about.js";
import { route_404 } from "./routes/404.js";

const app = new Application();
const port = 8080;

app.use(async (ctx) => {
  console.log(ctx.request.url.pathname);
  await send(ctx, ctx.request.url.pathname, {
    root: `${Deno.cwd()}/public`,
  });
});
app.use(route_home.routes());
app.use(route_login.routes());
app.use(route_admin.routes());
app.use(route_project.routes());
app.use(route_about.routes());
app.use(route_404.routes());

await app.listen({ port: port });

这是 Admin 路由的 admin.js

import { Router } from "https://deno.land/x/oak/mod.ts";
import { renderFile } from "https://deno.land/x/dejs@0.10.2/mod.ts";

const router = new Router();

export const route_admin = router
  .get("/admin", async (ctx) => {
    console.log(ctx);
    const body = renderFile(Deno.cwd() + "/views/adminDashboard.ejs");
    ctx.response.body = await body;
  })
  .get("/admin/project-list", async (ctx) => {
    const body = renderFile(Deno.cwd() + "/views/adminProjectsList.ejs");
    ctx.response.body = await body;
  })
  .get("/admin/project/:id", async (ctx) => {
    const body = renderFile(Deno.cwd() + "/views/adminProjectSingle.ejs");
    ctx.response.body = await body;
  })
  .get("/admin/edit-other-pages", async (ctx) => {
    const body = renderFile(Deno.cwd() + "/views/adminOtherPages.ejs");
    ctx.response.body = await body;
  })
  .get("/admin/user-account", async (ctx) => {
    const body = renderFile(Deno.cwd() + "/views/adminUserAccount.ejs");
    ctx.response.body = await body;
  });

有什么想法吗?

更新代码

app.use(async (ctx, next) => {
  try {
    const dirPath = `${Deno.cwd()}/public`;
    if (existsSync(dirPath)) {
      console.log("yes, dir exists");
      for await (const file of Deno.readDir(dirPath)) {
        console.log("file: ", file);
      }
      await send(ctx, ctx.request.url.pathname, {
        root: `${Deno.cwd()}/public`,
      });
    }

    await next();
  } catch (error) {
    console.log("error: ", error);
  }
});

文件结构:

现在出现以下错误:

[uncaught application error]: Http - error from user's HttpBody stream: body write aborted

    at async HttpConn.nextRequest (deno:ext/http/01_http.js:67:23)
    at async serve (https://deno.land/x/oak@v10.1.0/http_server_native.ts:237:34)
[uncaught application error]: Http - error from user's HttpBody stream: body write aborted

并在 chrome 控制台中:

Failed to load resource: the server responded with a status of 404 (Not Found)
Failed to load resource: the server responded with a status of 404 (Not Found)

我试试看! 我认为您的第一个中间件将尝试根据任何请求提供静态文件。您需要一种方法将您的静态文件与应用程序的其余部分区分开来。例如,您可以尝试将顺风查找放在 /public/tailwind.css 而不是 tailwind.css。然后你可以这样重写你的中间件:

app.use(async (ctx, next) => {
  if (ctx.request.url.pathname.startsWith('/public')) {
    const filename = ctx.request.url.pathname.substring(7)
    await send(ctx, filename, { root: 'public'})
  } else {
    await next()
  }
})

此实现检查文件是否应作为静态文件提供,然后在不带前缀的情况下提供它(否则它会尝试查找 /public/public/tailwind.css),但否则您需要调用 next 以传递给下一个中间件,这里是路由器中间件