我试图用Typescript为使用ExpressJS和NodeJS上传的静态文件提供服务,但出现404错误。
我想读的文件是/src/data/uploads/test.txt,我正试图直接从web浏览器访问它。
注意:当我用Javascript做它时,它起作用了,但在Typscript中不起作用。
index.ts文件(应用程序入口点(
import express from 'express';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import {cdg, config} from './utils';
import {Mongoose} from './db/monogdb';
import { setRoutes } from './routes/route.decorators';
import cors from 'cors';
import './routes';
const app = express();
app.use(helmet());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/ftp', express.static('data/uploads'));
setRoutes(app);
app.listen(config.server.port, () => {
cdg.konsole("Server connected! :: " + config.server.port + "!");
});
有没有一种特定的方法来用Typescript提供静态文件?
以下是express.static()
的工作原理。您显然遗漏了其中一个步骤,但您的问题缺乏详细信息,无法确定哪一步不正确。
首先,定义一个包含一些参数的express.static()
中间件。在您的案例中,您定义了:
app.use('/ftp', express.static('data/uploads'));
有四个因素决定了它的工作方式:
- 必须位于任何URL开头的
/ftp
才能匹配此中间件 - 传入的URL请求以及它是如何由浏览器根据您在HTML中指定的方式形成的
- 当前的工作目录与
data/uploads
结合以形成完整的路径引用,或者您可以构建自己的绝对路径,而不依赖于cwd express.static()
将尝试与传入URL的路径匹配的cwd + /data/uploads
中的文件
让我们进一步了解这些:
您的中间件将首先只查看以/ftp
开头的URL。然后,对于它看到的任何以/ftp
开头的URL,它应该将URL的其余部分附加到data/uploads
,并看到它在本地文件系统中找到匹配的文件。它将在请求时使用服务器进程中的当前工作目录来尝试解析相对路径data/uploads
。当前的工作目录(如果你还没有通过编程更改它(将取决于你的应用程序是如何启动的。
因此,如果你用node index.js
启动你的应用程序,那么当前的工作目录将是index.js
所在的目录,express static将在下面的data/uploads
子目录中查找'index.js'。
然后,我们需要了解指定该静态资源的HTML标记是如何指定的。
例如,假设这是一个<img>
标签。如果你指定这样的东西:
<img src="/ftp/hello.jpg">
然后,浏览器将向您的服务器创建一个/ftp/hello.jpg
请求。由于这确实是从/ftp
开始的,所以express.static()
中间件将使用路径/hello.jpg
的其余部分,并将其附加到data/uploads
,然后构建一个路径,如下所示:
path.join(process.cwd(), 'data/uploads', '/hello.jpg')
并且,它将在您的本地文件系统中查找生成的文件。如果它找到该文件,那么它将提供该文件并将其作为响应返回。如果它没有找到确切的文件,那么它将调用next()
并继续路由到其他路由处理程序。
有许多常见的错误(可能出错的事情(:
您没有在网页中指定与
express.static()
中间件行一致的正确URL(包括中间件指定的/ftp
前缀(。您的中间件没有完全指向文件系统中的正确目录,因此它永远找不到任何东西。
您在网页中使用的是相对URL,浏览器将其与网页的路径相结合,从而导致它请求与您想要的不同的内容。网页中的静态资源URL几乎总是以
/
开头,这样它们就不依赖于父页面的路径。这些文件在您使用中间件指向的文件层次结构中的位置不太正确(通常偏离一个级别(。
还有一件事我要提。由于您使用的是TypeScript,这意味着您必须将脚本编译/构建为常规.js脚本,然后才能运行。这通常位于不同的目录位置。
这种不同的目录位置为您提供了不引用静态资源所在的正确目录的机会,因为它们可能是相对于TypeScript文件而不是您正在运行的已构建Javascript文件(这取决于您的构建脚本(定位的。
同样,如果您向我们展示文件系统中的所有内容(TypeScript文件、构建的JS文件、静态资源(以及引用静态资源的HTML标记的样子,我们可以帮助您更具体地调试它。
在我的例子中,我这样解决了我的问题:在相对于目录路径的参数中,我使用path.resolve,在它的第一个参数中,使用__dirname作为第一个参数,目标目录的相对路径作为第二个参数。
app.get('/', express.static(path.resolve(__dirname, '../static/'))); –