javascript 使用 Meteor 生成和提供静态文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13201723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
generating and serving static files with Meteor
提问by bento
I'm looking to create static text files based upon the content of a supplied object, which can then be downloaded by the user. Here's what I was planning on doing:
我希望根据提供的对象的内容创建静态文本文件,然后用户可以下载这些文件。这是我打算做的事情:
When the user hits 'export' the application calls a
Meteor.method()
which, in turn, parses and writes the file to the public directory using typical Node methods.Once the file is created, in the callback from
Meteor.method()
I provide a link to the generated file. For example, 'public/userId/file.txt'. The user can then choose to download the file at that link.I then use Meteor's
Connect modele
(which it uses internally) to route any requests to the above URL to the file itself. I could do some permissions checking based on the userId and the logged in state of the user.
当用户点击“export”时,应用程序调用 a
Meteor.method()
,然后使用典型的 Node 方法解析文件并将其写入公共目录。创建文件后,在来自
Meteor.method()
我的回调中提供指向生成文件的链接。例如,'public/userId/file.txt'。然后,用户可以选择从该链接下载文件。然后我使用 Meteor 的
Connect modele
(它在内部使用)将任何对上述 URL 的请求路由到文件本身。我可以根据 userId 和用户的登录状态进行一些权限检查。
The problem: When static files are generated in public, the web page automatically reloads each time. I thought that it might make more sense to use something like Express to generate a REST endpoint, which could deal with creating the files. But then I'm not sure how to deal with permissions if I don't have access to the Meteor session data.
问题:公开生成静态文件时,网页每次都会自动重新加载。我认为使用 Express 之类的东西来生成 REST 端点可能更有意义,它可以处理创建文件。但是如果我无权访问 Meteor 会话数据,我不确定如何处理权限。
Any ideas on the best strategy here?
关于最佳策略的任何想法?
采纳答案by Jacott
The symlink hack will no longer work in Meteor (from 0.6.5). Instead I suggest creating a package with similar code to the following:
符号链接 hack 将不再适用于 Meteor(从 0.6.5 开始)。相反,我建议使用与以下类似的代码创建一个包:
packge.js
packge.js
Package.describe({
summary: "Application file server."
});
Npm.depends({
connect: "2.7.10"
});
Package.on_use(function(api) {
api.use(['webapp', 'routepolicy'], 'server');
api.add_files([
'app-file-server.js',
], 'server');
});
app-file-server.js
app-file-server.js
var connect = Npm.require('connect');
RoutePolicy.declare('/my-uploaded-content', 'network');
// Listen to incoming http requests
WebApp.connectHandlers
.use('/my-uploaded-content', connect.static(process.env['APP_DYN_CONTENT_DIR']));
回答by Matyas
In version 0.6.6.30.7.x- 1.3.xyou can do the following:
在版本 0.6.6.30.7.x- 1.3.x您可以执行以下操作:
To write
来写
var fs = Npm.require('fs');
var filePath = process.env.PWD + '/.uploads_dir_on_server/' + fileName;
fs.writeFileSync(filePath, data, 'binary');
To serve
服务
In vanilla meteor app
在香草流星应用程序中
var fs = Npm.require('fs');
WebApp.connectHandlers.use(function(req, res, next) {
var re = /^\/uploads_url_prefix\/(.*)$/.exec(req.url);
if (re !== null) { // Only handle URLs that start with /uploads_url_prefix/*
var filePath = process.env.PWD + '/.uploads_dir_on_server/' + re[1];
var data = fs.readFileSync(filePath);
res.writeHead(200, {
'Content-Type': 'image'
});
res.write(data);
res.end();
} else { // Other urls will have default behaviors
next();
}
});
When using iron:router
使用铁时:路由器
This should be a server side route (ex: defined in a file in /server/
folder)
这应该是服务器端路由(例如:在文件/server/
夹中的文件中定义)
Edit (2016-May-9)
编辑(2016 年 5 月 9 日)
var fs = Npm.require('fs');
Router.route('uploads', {
name: 'uploads',
path: /^\/uploads_url_prefix\/(.*)$/,
where: 'server',
action: function() {
var filePath = process.env.PWD + '/.uploads_dir_on_server/' + this.params[0];
var data = fs.readFileSync(filePath);
this.response.writeHead(200, {
'Content-Type': 'image'
});
this.response.write(data);
this.response.end();
}
});
Outdated format:
过时的格式:
Router.map(function() {
this.route('serverFile', {
...// same as object above
}
});
Notes
笔记
process.env.PWD
will give you the project rootif you plan to put files inside your project
- don't use the
public
orprivate
meteor folders - use dot folders (eg. hidden folders ex:
.uploads
)
Not respecting these two will cause local meteor to restart on every upload, unless you run your meteor app with:
meteor run --production
- don't use the
- I've used this approach for a simple image upload & serve (based on dario's version)
- Should you wish for more complex file management please consider CollectionFS
process.env.PWD
会给你项目根如果您打算将文件放入项目中
- 不要使用
public
或private
流星文件夹 - 使用点文件夹(如的隐藏文件夹例如:。
.uploads
)
不尊重这两个将导致本地流星在每次上传时重新启动,除非您使用以下命令运行流星应用程序:
meteor run --production
- 不要使用
- 我已经将这种方法用于简单的图像上传和服务(基于dario的版本)
- 如果您希望进行更复杂的文件管理,请考虑CollectionFS
回答by dustin.b
I was stuck at the exact same problem, where i need the users to upload files in contrast to your server generated files. I solved it sort of by creating an "uploads" folder as sibling to the "client public server" on the same folder level. and then i created a simbolic link to the '.meteor/local/build/static' folder like
我遇到了完全相同的问题,我需要用户上传与服务器生成的文件相反的文件。我通过在同一文件夹级别创建一个“上传”文件夹作为“客户端公共服务器”的兄弟来解决它。然后我创建了一个指向“.meteor/local/build/static”文件夹的符号链接,例如
ln -s ../../../../uploads .meteor/local/build/static/
but with nodejs filesystem api at server start time
但是在服务器启动时使用 nodejs 文件系统 api
Meteor.startup(function () {
var fs = Npm.require('fs');
fs.symlinkSync('../../../../uploads', '.meteor/local/build/static/uploads');
};
in your case you may have a folder like "generatedFiles" instead of my "uploads" folder you need to do this every time the server starts up cuz these folders are generated every time the server starts up e.g. a file changes in your implementation.
在您的情况下,您可能有一个类似“generatedFiles”的文件夹而不是我的“uploads”文件夹,您需要在每次服务器启动时执行此操作,因为每次服务器启动时都会生成这些文件夹,例如您的实现中的文件更改。
回答by Sean
Another option is to use a server side route to generate the content and send it to the user's browser for download. For example, the following will look up a user by ID and return it as JSON. The end user is prompted to save the response to a file with the name specified in the Content-Disposition header. Other headers, such as Expires, could be added to the response as well. If the user does not exist, a 404 is returned.
另一种选择是使用服务器端路由来生成内容并将其发送到用户的浏览器进行下载。例如,以下将按 ID 查找用户并将其作为 JSON 返回。系统会提示最终用户将响应保存到一个文件,其名称在 Content-Disposition 标头中指定。其他标头,例如 Expires,也可以添加到响应中。如果用户不存在,则返回 404。
Router.route("userJson", {
where: "server",
path: "/user-json/:userId",
action: function() {
var user = Meteor.users.findOne({ _id: this.params.userId });
if (!user) {
this.response.writeHead(404);
this.response.end("User not found");
return;
}
this.response.writeHead(200, {
"Content-Type": "application/json",
"Content-Disposition": "attachment; filename=user-" + user._id + ".json"
});
this.response.end(JSON.stringify(user));
}
});
This method has one big downside, however. Server side routes do not provide an easy way to get the currently logged in user. See this issue on GitHub.
然而,这种方法有一个很大的缺点。服务器端路由不提供获取当前登录用户的简单方法。在 GitHub 上查看此问题。