Angular 文件上传2025年3月17日 | 阅读 7 分钟 我们将了解如何创建一个功能性的 Angular 文件上传组件,该组件需要上传具有给定扩展名的文件,并通过 **HTTP POST** 调用将文件发送到后端。 自定义组件将具有上传加载指示器,并支持上传取消。我们将提供一个示例(在 Node 中)来处理后端的文件。 如何将文件上传到浏览器要创建 Angular 文件上传组件,我们首先需要了解如何在纯 HTML 和 JavaScript 中上传文件,然后在此基础上进行开发。 用于将文件上传到浏览器的主要组件是普通 **HTML** 的文件类型输入框。 此输入框允许用户打开浏览器文件选择对话框并选择一个或多个文件(默认情况下)。输入框的外观如下: ![]() 您可以通过文件输入框选择一个文件,然后通过少量 JavaScript,将其发送到后端。 为什么我们不经常看到文件输入框?这个普通文件输入框的问题在于它默认很难进行样式设置。某些应用的样式无法更改,我们甚至无法更改按钮上的文本! 这是默认的浏览器行为,无法更改,这也是为什么我们在日常使用的界面(如 Gmail 等)中不常看到这种普通文件输入框的原因。 由于无法正确设置此文件输入框的样式,最常见的选择是永远不向最终用户显示它。 文件类型输入框是如何工作的?当用户使用文件上传对话框选择文件时,会触发一个类型为 `change` 的事件。然后,该事件将包含用户在目标上选择的文件列表。 这是用户选择文件后我们在控制台中看到的输出:{ lastModified: 1601984029839 lastModifiedDate: Tue Oct 06 2020 13:33:49 GMT+0200 (Central European Summer Time) name: "angular-forms-course-small.jpg" size: 56411 type: "image/jpeg" webkitRelativePath: "" } 当 `change` 事件触发时,浏览器文件不会自动上传到后端。相反,我们需要在响应 `change` 事件时自己触发一个 HTTP 请求。 创建文件上传组件的用户界面无法正确设置普通文件类型输入框的样式,我们将其隐藏起来,然后构建一个备用的文件上传 UI,该 UI 在后台使用文件输入框。 文件上传组件的初始模板用户界面分为两个不同的部分。顶部有一个普通的文件输入框,用于打开文件上传对话框并处理 `change` 事件。 正如我们在组件 **CSS** 中看到的,这个普通文本输入框对用户是隐藏的。 我们有一个 `file-upload` 容器 div,其中包含用户可以在屏幕上看到的实际 **UI**。 例如,我们使用 Angular Material 组件构建了这个 UI,但当然,可选的文件上传 UI 可以采用任何您喜欢的形式。 这个 UI 可以是一个对话框、一个拖放区域,或者像我们的组件一样,只是一个 styled 按钮。 ![]() 请注意,在组件模板中,上传蓝色按钮和不可见的文件输入框是如何连接起来的。当用户点击蓝色按钮时,一个 click 事件处理器通过 **fileUpload.click()** 触发文件输入框。 然后用户将从文件上传对话框中选择一个文件,`change` 事件将被触发并由 **onFileSelected()** 处理。 使用 Angular HTTP 客户端将文件上传到后端现在让我们看一下我们的组件类和 **onFileSelected()** 的实现: 这是组件:我们通过访问 `event.target.files` 属性来获取用户已选择文件的引用。 然后我们使用 `FormData` API 创建表单载荷。这是一个标准的浏览器 API,并非 Angular 特有。 我们使用 Angular HTTP 客户端来发出 HTTP 请求,并将文件发送到后端。 至此,我们已经拥有了一个可用的文件上传组件。 如何显示文件上传进度指示器我们在文件上传组件的 UI 中添加了一些额外的元素。这是文件上传组件模板: 我们添加到 UI 中的两个主要元素是:
如何知道文件上传了多少?我们通过使用 Angular HTTP 客户端的报告进度功能来实现进度指示器。 使用此功能,我们可以通过 **HTTP** Observables 发出的多个事件来获取文件上传进度的通知。 为了看到这一点,让我们看一下文件上传组件类的最终版本,该版本已实现所有功能: 正如我们所见,我们在 HTTP 调用中将 `reportProgress` 属性设置为 `true`,并且还在 `value` 事件中设置了 `observe` 属性。 我们将收到一个事件对象,报告 HTTP 请求的进度。 这些事件将作为 `http$` observable 的值发出,并且有不同的类型:
我们可以通过使用 RxJs 的 `finalize` 操作符来确保这一点,该操作符将在两种情况下(上传成功或失败)调用 `reset()` 方法。 如何取消正在进行的文件上传为了支持文件上传取消,当 `http$` observable 被订阅时,我们必须引用 RxJs 的 `Subscription` 对象。 在我们的组件中,我们将这个成员对象存储在 `uploadSub` 成员变量中。 当上传仍在进行时,用户可以通过单击“取消”按钮来取消它。然后调用 `cancelUpload()` 方法,可以通过取消订阅 `uploadSub` 订阅来取消 HTTP 请求。 取消此订阅将立即取消正在进行的文件上传。 如何接受特定类型的文件在我们文件上传组件的最终版本中,我们可以要求用户使用 `requiredFileType` 属性上传特定类型的文件。 此属性会传递给 **文件上传模板** 中文件输入框的 `accept` 属性,强制用户从文件上传对话框中选择 PNG 文件。 如何上传多个文件浏览器文件选择对话框默认只允许用户选择一个文件进行上传。 但是,通过使用 `multiple` 属性,我们可以允许用户选择多个文件。 请注意,这将需要与我们创建的 UI 完全不同的 UI。带进度指示器的 styled 上传按钮适用于单个文件上传。 对于多文件上传场景,可以创建各种 UI:一个带有所有文件上传进度的浮动对话框等。 在 Node 后端处理上传的文件。如何在后端处理上传的文件取决于您使用的技术,但让我们通过 Node 和 Express 框架快速示例来说明如何操作。 我们首先需要安装 `express-fileupload` 包。然后我们可以将此包作为中间件添加到我们的 express 应用程序中。 我们要做的是定义一个 express 路由来处理文件上传请求。 总结在 Angular 中处理文件上传的最佳方法是根据支持的上传场景构建一个或多个自定义组件。 文件上传组件必须包含一个 HTML 输入类型为 `file` 的元素,该元素允许用户从文件系统中选择一个或多个文件。 此文件输入框对用户是隐藏的,因为它无法设置样式,应该被一个更友好的 UI 取代。 通过在后台使用文件输入框,我们可以通过 `change` 事件引用文件,然后使用该事件发出 HTTP 请求并将文件发送到后端。 下一个主题Angular Flex 布局 |
我们请求您订阅我们的新闻通讯以获取最新更新。