express框架前端交互(使用Express和)
express框架前端交互(使用Express和)取自官方文档,浏览器支持如下:总结一下插件的一些特性和特点,DropzoneJS:然而,DropzoneJS 不仅仅是一个基于拖放的小部件。单击小部件会启动更传统的文件选择器对话框方法。这是小部件的动画效果:您可以将 DropzoneJS 用于任何类型的文件,尽管漂亮的小缩略图效果使其特别适合上传图像。
在可以组成表单的所有组件中,文件控件可能是最令人沮丧的。样式真的很痛苦,使用起来笨重且笨拙,上传文件会减慢任何表单的提交过程。
这就是为什么增强它们的插件总是值得一看的,而DropzoneJS就是这样一个选择。它将使您的文件上传控件看起来更好,使它们更加用户友好,并且通过使用 AJAX 在后台上传文件,它至少会使过程看起来更快。它还可以在文件到达您的服务器之前更轻松地验证文件,从而为用户提供近乎即时的反馈。
我们将详细了解 DropzoneJS。我们将展示如何实现它。并查看一些可以对其进行调整和定制的方法。我们还将使用 Node.js 实现一个简单的服务器端上传机制。
介绍 DropzoneJSDropzoneJS 允许用户使用拖放上传文件。尽管对可用性的好处值得争论,但这是一种越来越普遍的方法,并且与许多人在桌面上处理文件的方式相一致。它在主要浏览器中也得到了很好的支持。
然而,DropzoneJS 不仅仅是一个基于拖放的小部件。单击小部件会启动更传统的文件选择器对话框方法。
这是小部件的动画效果:
您可以将 DropzoneJS 用于任何类型的文件,尽管漂亮的小缩略图效果使其特别适合上传图像。
特征总结一下插件的一些特性和特点,DropzoneJS:
- 可以在有或没有 jQuery 的情况下使用
- 具有拖放支持
- 生成缩略图
- 支持多个上传,可选择并行
- 包括一个进度条
- 完全可主题化
- 包括可扩展的文件验证支持
- 可作为 AMD 模块或 RequireJS 模块使用
- 压缩时大约为 43KB,压缩时大约为 13KB
取自官方文档,浏览器支持如下:
- 铬 7
- 火狐 4
- IE 10
- Opera 12 (macOS 的版本 12 被禁用,因为它们的 API 有问题)
- 野生动物园 6
当插件不完全支持时,有几种方法可以处理回退,我们稍后会介绍。
开始设置开始使用 DropzoneJS 的最简单方法是包含来自 CDN 的最新版本。在撰写本文时,这是 version 5.5.1。
或者,您可以从项目的 GitLab 页面下载最新版本。还有一个第三方包为ReactJS提供支持。
然后,确保在页面中包含主 JavaScript 文件和 CSS 样式。例如:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload Example</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.css">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.js"></script>
</body>
</html>
请注意,该项目提供了两个 CSS 文件——一个basic.css具有一些最小样式的文件和一个更广泛的dropzone.css文件。dropzone.css和的缩小版本dropzone.js也可用。
基本用法实现插件的最简单方法是将其附加到表单中,尽管您可以使用任何 HTML,例如<div>. 然而,使用表单意味着要设置的选项更少——尤其是 URL,它是最重要的配置属性。
dropzone您可以简单地通过添加类来初始化它。例如:
<form id="upload-widget" method="post" action="/upload" class="dropzone"></form>
从技术上讲,这就是您需要做的所有事情,但在大多数情况下,您需要设置一些额外的选项。其格式如下:
Dropzone.options.WIDGET_ID = {
//
};
要派生用于设置选项的小部件 ID,请使用您在 HTML 中定义的 ID 并将其转换为驼峰式。例如,upload-widget变为uploadWidget:
Dropzone.options.uploadWidget = {
//
};
您还可以通过编程方式创建实例:
const uploader = new Dropzone('#upload-widget' options);
接下来,我们将看看一些可用的配置选项。
基本配置选项该url选项定义上传表单的目标,并且是唯一必需的参数。也就是说,如果您将它附加到表单元素,那么它只会使用表单的action属性,在这种情况下您甚至不需要指定它。
该method选项再次设置 HTTP 方法,如果您使用该方法,它将从表单元素中获取它,否则它将简单地默认为POST,这应该适合大多数情况。
该paramName选项用于设置上传文件的参数名称。如果您使用的是文件上传表单元素,它将匹配该name属性。如果不包含它,则默认为file.
maxFiles如果未设置为 null,则设置用户可以上传的最大文件数。
默认情况下,小部件在单击时会显示一个文件对话框,但您可以使用该clickable参数将其设置为 来禁用它false,或者您可以提供 HTML 元素或 CSS 选择器来自定义可单击元素。
这些是基本选项,但现在让我们看一些更高级的选项。
强制执行最大文件大小该maxFilesize属性确定最大文件大小(以 MB 为单位)。这默认为 1000 字节的大小,但使用该filesizeBase属性,您可以将其设置为另一个值 - 例如,1024 字节。您可能需要对此进行调整,以确保您的客户端和服务器代码以完全相同的方式计算任何限制。
限制为某些文件类型该acceptedFiles参数可用于限制要接受的文件类型。这应该采用逗号分隔的 MIME 类型列表的形式,尽管您也可以使用通配符。
例如,只接受图像:
acceptedFiles: 'image/*'
修改缩略图的大小
默认情况下,缩略图以 120x120 像素生成。也就是说,它是正方形的。有几种方法可以修改此行为。
第一个是使用thumbnailWidth和/或thumbnailHeight配置选项。
如果同时设置thumbnailWidth和thumbnailHeight,null则缩略图根本不会调整大小。
如果您想完全自定义缩略图生成行为,您甚至可以覆盖该resize功能。
关于修改缩略图大小的重要一点是,dz-image包提供的类在 CSS 中设置了缩略图大小,因此您也需要相应地修改它。
附加文件检查该accept选项允许您提供额外的检查以确定文件在上传之前是否有效。您不应该使用它来检查文件数 ( maxFiles)、文件类型 ( acceptedFiles) 或文件大小 ( maxFilesize),但您可以编写自定义代码来执行其他类型的验证。
你会使用这样的accept选项:
accept: function(file done) {
if (!someCheck()) {
return done('This is invalid!');
}
return done();
}
如您所见,它是异步的。您可以done()在没有参数和验证通过的情况下调用,或者提供错误消息并且文件将被拒绝,并在文件旁边显示消息作为弹出窗口。
稍后,当我们研究如何强制最小或最大图像尺寸时,我们将看一个更复杂的真实示例。
发送附加标头通常,您需要在上传者的 HTTP 请求中附加额外的标头。
例如,CSRF(跨站点请求伪造)保护的一种方法是在视图中输出一个令牌,然后让您的POST/PUT/DELETE端点检查请求标头中的有效令牌。假设您像这样输出令牌:
<meta name="csrf-token" content="CL2tR2J4UHZXcR9BjRtSYOKzSmL8U1zTc7T8d6Jz">
然后,您可以将其添加到配置中:
headers: {
'x-csrf-token': document.querySelector('meta[name=csrf-token]').getAttributeNode('content').value
}
或者,这是相同的示例,但使用 jQuery:
headers: {
'x-csrf-token': $('meta[name="csrf-token"]').attr('content')
}
然后,您的服务器应该验证x-csrf-token标头,可能使用一些中间件。
处理回退实现回退的最简单方法是将 a 插入<div>到包含输入控件的表单中,将元素上的类名设置为fallback. 例如:
<form id="upload-widget" method="post" action="/upload" class="dropzone">
<div class="fallback">
<input name="file" type="file" />
</div>
</form>
fallback或者,您可以使用配置参数提供在浏览器不支持插件时执行的功能。
forceFallback您可以通过设置为来强制小部件使用回退行为true,这在开发过程中可能会有所帮助。
处理错误error您可以通过使用配置参数提供自定义函数来自定义小部件处理错误的方式。第一个参数是文件,第二个参数是错误消息,如果错误发生在服务器端,第三个参数将是XMLHttpRequest.
与往常一样,客户端验证只是成功的一半。您还必须在服务器上执行验证。当我们稍后实现一个简单的服务器端组件时,我们将查看错误响应的预期格式,如果正确配置,它将以与客户端错误相同的方式显示(如下图所示)。
覆盖消息和翻译有许多额外的配置属性可以设置小部件显示的各种消息。您可以使用这些自定义显示的文本,或将它们翻译成另一种语言。
最值得注意的是,dictDefaultMessage用于在有人选择要上传的文件之前设置出现在放置区中间的文本。
您将在文档中找到可配置字符串值的完整列表(所有这些值都以开头dict)。
活动您可以收听许多事件以自定义或增强插件。
有两种方法可以监听事件。第一个是在初始化函数中创建一个监听器:
Dropzone.options.uploadWidget = {
init: function() {
this.on('success' function(file resp){
...
});
}
...
};
这是另一种方法,如果您决定以编程方式创建 Dropzone 实例,这很有用:
const uploader = new Dropzone('#upload-widget');
uploader.on('success' function(file resp){
...
});
也许最值得注意的方面是success事件,它在文件成功上传时触发。回调有两个参数:第success一个是文件对象,第二个是XMLHttpRequest.
其他有用的事件包括addedfileand removedfile,用于在上传列表中添加或删除文件时;thumbnail,一旦生成缩略图就会触发;和uploadprogress,您可以使用它来实现自己的进度表。
还有一堆事件将事件对象作为参数,您可以使用它们来自定义小部件本身的行为—— drop、dragstart、dragend、dragenter和。dragoverdragleave
您可以在文档的相关部分找到完整的事件列表。
更复杂的验证示例:图像尺寸之前我们查看了异步accept()选项,您可以使用它在文件上传之前对文件运行检查(验证)。
上传图像时的一个常见要求是强制执行最小或最大图像尺寸。我们可以使用 DropzoneJS 做到这一点,尽管它稍微复杂一些。
虽然接受回调接收一个文件对象,但为了检查图像尺寸,我们需要等到生成缩略图,此时尺寸将在文件对象上设置。为此,我们需要监听缩略图事件。
这是代码。在此示例中,我们在上传之前检查图像是否至少为 640x480 像素:
init: function() {
this.on('thumbnail' function(file) {
if (file.accepted !== false) {
if (file.width < 1024 || file.height < 768) {
file.rejectDimensions();
}
else {
file.acceptDimensions();
}
}
});
}
accept: function(file done) {
file.acceptDimensions = done;
file.rejectDimensions = function() {
done('The image must be at least 1024 by 768 pixels in size');
};
}
一个完整的例子
经历了选项、事件和一些更高级的验证之后,让我们看一个完整且相对全面的示例。显然,我们并没有利用所有可用的配置选项,因为有这么多——使其非常灵活。
这是表单的 HTML:
<form id="upload-widget" method="post" action="/upload" class="dropzone">
<div class="fallback">
<input name="file" type="file" />
</div>
</form>
如果您正在实施 CSRF 保护,您可能希望在布局中添加类似这样的内容:
<head>
<!-- -->
<meta name="csrf-token" content="XYZ123">
</head>
现在是 JavaScript。注意我们没有使用 jQuery!
Dropzone.options.uploadWidget = {
paramName: 'file'
maxFilesize: 2 // MB
maxFiles: 1
dictDefaultMessage: 'Drag an image here to upload or click to select one'
headers: {
'x-csrf-token': document.querySelectorAll('meta[name=csrf-token]')[0].getAttributeNode('content').value
}
acceptedFiles: 'image/*'
init: function() {
this.on('success' function(file resp){
console.log(file);
console.log(resp);
});
this.on('thumbnail' function(file) {
if (file.accepted !== false) {
if (file.width < 640 || file.height < 480) {
file.rejectDimensions();
}
else {
file.acceptDimensions();
}
}
});
}
accept: function(file done) {
file.acceptDimensions = done;
file.rejectDimensions = function() {
done('The image must be at least 640 x 480px')
};
}
};
主题化
有许多方法可以自定义小部件的外观和感觉,而且确实可以完全改变它的外观。
作为外观可定制程度的示例,这里有一个小部件的演示,该小部件经过调整,看起来和感觉与使用 Bootstrap的jQuery 文件上传小部件完全一样。
显然,改变小部件外观的最简单方法是使用 CSS。小部件有一个类,dropzone它的组件元素有一个类前缀dz-——例如,dz-clickable用于放置区域内的可点击区域,dz-message用于标题,dz-preview用于dz-image-preview包装每个上传文件的预览,等等。查看dropzone.css文件以供参考。
您可能还希望将样式应用于悬停状态 - 即,当用户在释放鼠标按钮开始上传之前将文件悬停在放置区域上时。您可以通过设置类的样式来做到这一点,dz-drag-hover该类由插件自动添加。
除了 CSS 调整之外,您还可以通过设置previewTemplate配置属性来自定义构成预览的 HTML。这是默认预览模板的外观:
<div class="dz-preview dz-file-preview">
<div class="dz-image">
<img data-dz-thumbnail />
</div>
<div class="dz-details">
<div class="dz-size">
<span data-dz-size></span>
</div>
<div class="dz-filename">
<span data-dz-name></span>
</div>
</div>
<div class="dz-progress">
<span class="dz-upload" data-dz-uploadprogress></span>
</div>
<div class="dz-error-message">
<span data-dz-errormessage></span>
</div>
<div class="dz-success-mark">
<svg>REMOVED FOR BREVITY</svg>
</div>
<div class="dz-error-mark">
<svg>REMOVED FOR BREVITY</svg>
</div>
</div>
如您所见,您可以完全控制文件排队等待上传后的渲染方式以及成功和失败状态。
关于使用 DropzoneJS 插件的部分到此结束。总结一下,让我们看看如何让它与服务器端代码一起工作。
一个带有 Node.js 和 Express 的简单服务器端上传处理程序当然,您可以使用任何服务器端技术来处理上传的文件。为了演示如何将您的服务器与插件集成,我们将使用 Node.js 和Express构建一个非常简单的示例。
为了处理上传的文件本身,我们将使用Multer,这是一个提供一些 Express 中间件的包,这使得它变得非常容易。事实上,这很容易:
const upload = multer({ dest: 'uploads/' });
app.post('/upload' upload.single('file') (req res next) => {
// Metadata about the uploaded file can now be found in req.file
});
在我们继续实施之前,在处理像 DropzoneJS 这样在幕后向您发出请求的插件时,最明显的问题是:“它期望什么样的响应?”
处理上传成功如果上传过程成功,就您的服务器端代码而言,唯一的要求是返回2xx响应代码。您回复的内容和格式完全取决于您,并且可能取决于您如何使用它。例如,您可能会返回一个 JSON 对象,其中包含上传文件的路径,或自动生成的缩略图的路径。出于本示例的目的,我们将简单地返回文件对象的内容——即 Multer 提供的一堆元数据:
return res.status(200).send(req.file);
响应将如下所示:
{ fieldname: 'file'
originalname: 'myfile.jpg'
encoding: '7bit'
mimetype: 'image/jpeg'
destination: 'uploads/'
filename: 'fbcc2ddbb0dd11858427d7f0bb2273f5'
path: 'uploads/fbcc2ddbb0dd11858427d7f0bb2273f5'
size: 15458 }
处理上传错误
如果你的响应是 JSON 格式——也就是说,你的响应类型设置为application/json——那么 DropzoneJS 默认错误插件期望响应看起来像这样:
{
error: 'The error message'
}
如果您不使用 JSON,它只会使用响应正文。例如:
return res.status(422).send('The error message');
让我们通过对上传的文件执行几个验证检查来证明这一点。我们将简单地复制我们在客户端上执行的检查。请记住,客户端验证本身是不够的。
要验证文件是否为图像,我们只需检查 MIME 类型是否以image/. ES6String.prototype.startsWith()非常适合这一点。
下面是我们如何运行该检查,如果失败,则以 Dropzone 的默认错误处理程序期望的格式返回错误:
if (!req.file.mimetype.startsWith('image/')) {
return res.status(422).json({
error: 'The uploaded file must be an image'
});
}
注意:我使用 HTTP 状态代码 422,无法处理的实体,验证失败,但 400 错误请求同样有效。事实上,任何超出 2xx 范围的内容都会导致插件报告错误。
我们还要检查图像是否具有一定的大小。image-size包使获取图像尺寸变得非常简单。您可以异步或同步使用它。我们将使用后者来保持简单:
const dimensions = sizeOf(req.file.path);
if ((dimensions.width < 640) || (dimensions.height < 480)) {
return res.status(422).json({
error: 'The image must be at least 640 x 480px'
});
}
让我们将所有这些放在一个完整的(迷你)应用程序中:
const express = require('express');
const multer = require('multer');
const upload = multer({ dest:'uploads/'});
const sizeOf = require('image-size');
const exphbs = require('express-handlebars');
const app = express();
app.use(express.static(__dirname '/public'));
app.engine('.hbs' exphbs({ extname:'.hbs'}));
app.set('view engine' '.hbs');
app.get('/' (req res) => {
return res.render('index' {layout: false});
});
app.post('/upload' upload.single('file') (req res) => {
if (!req.file.mimetype.startsWith('image/')) {
return res.status(422).json({
error :'The uploaded file must be an image'
});
}
const dimensions = sizeOf(req.file.path);
if ((dimensions.width < 640) || (dimensions.height < 480)) {
return res.status(422).json({
error :'The image must be at least 640 x 480px'
});
}
return res.status(200).send(req.file);
});
app.listen(8080 () => {
console.log('Express server listening on port 8080');
});
注意:为简洁起见,此服务器端代码未实现 CSRF 保护。你可能想看看像 CSURF这样的包。
概括DropzoneJS 是一个功能强大且高度可定制的 JavaScript 插件,用于增强您的文件上传控件和执行 AJAX 上传。在本教程中,我们查看了一些可用选项、事件以及如何自定义插件。