前言
在《文件直传 OSS 实践(一):服务端篇》文章中讲解了如何在服务端生成用于客户端直传 OSS 的直传传凭证,本文讲解在使用 Angular 框架的 Web 页面中将文件直传 OSS 的整体流程。相对于在小程序中使用已经由官方封装好的上传方法,在 Angular 中使用上传功能会稍微复杂一些。
获取直传凭证
我们假定获取直传凭证的 API 为:
GET https://api.xxx.com/upload/token
复制代码
可以将请求获取直传传凭证的过程进行封装(为方便演示,将所有的方法均放在了 app.component.ts
文件中,实际上涉及 HTTP 请求的方法应放在 *.service.ts
文件中):
// app.component.ts
import { HttpClient } from '@angular/common/http'
import { Component } from '@angular/core'
/** 直传凭证 */
export interface UploadToken {
key: string
policy: string
signature: string
OSSAccessKeyId: string
url: string
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
constructor(private http: HttpClient) {}
token!: UploadToken
/** 获取直传凭证 */
getUploadToken() {
this.http.get('https://api.xxx.com/upload/token').subscribe((data: UploadToken) => {
this.token = data
})
}
}
复制代码
选择文件
相对于在小程序中可以直接使用 wx.chooseMedia
方法获取资源的路径,在 Angular 获取资源的路径会稍微复杂一些,需要在文档中获取到上传文件使用的子组件,然后再在其内部获取到文件路径。
首先,定义 HTML 模板。
// app.component.html
<input #uploader type="file" />
复制代码
这是一个获取文件的输入框,其中 #uploader
表示模板名,可用于在 *.component.ts
文件中获取该模板。需要使用 ViewChild
装饰器获取该模板。
import { HttpClient } from '@angular/common/http'
import { Component, ElementRef, ViewChild } from '@angular/core'
/** 直传凭证 */
export interface UploadToken {
key: string
policy: string
signature: string
OSSAccessKeyId: string
url: string
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
constructor(private http: HttpClient) {}
@ViewChild('uploader')
FileElement!: ElementRef
token!: UploadToken
/** 获取直传凭证 */
getUploadToken() {
this.http.get('https://api.xxx.com/upload/token').subscribe((data: UploadToken) => {
this.token = data
})
}
/** 显示第一个文件的路径 */
showFile() {
console.log(this.FileElement.nativeElement.files[0])
}
}
复制代码
核心部分为:
@ViewChild('uploader')
FileElement!: ElementRef
复制代码
其中,各部分的含义是: (1)'uploader'
与 <input #uploader type="file" />
中的 uploader
对应。 (2)!
为非空断言。
在点击绑定的按钮选择文件后,调用 showFile
方法可以查看选中的文件。
上传文件
获取到文件和上传凭证后,然后进行上传流程。这里需要注意的一点是:在添加 FormData
属性时,需要把 file
项放在最后,否则会失败。
import { HttpClient } from '@angular/common/http'
import { Component, ElementRef, ViewChild } from '@angular/core'
/** 直传凭证 */
export interface UploadToken {
key: string
policy: string
signature: string
OSSAccessKeyId: string
url: string
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
constructor(private http: HttpClient) {}
@ViewChild('uploader')
FileElement!: ElementRef
token!: UploadToken
/** 获取直传凭证 */
getUploadToken() {
this.http.get('https://api.xxx.com/upload/token').subscribe((data: UploadToken) => {
this.token = data
})
}
/** 显示第一个文件的路径 */
showFile() {
console.log(this.FileElement.nativeElement.files[0])
}
/** 直传至 OSS */
upload() {
const file = this.FileElement.nativeElement.files[0]
const formData = new FormData()
formData.append('OSSAccessKeyId', this.token.OSSAccessKeyId)
formData.append('key', this.token.key)
formData.append('policy', this.token.policy)
formData.append('signature', this.token.signature)
formData.append('file', file)
this.http.post(this.token.url, formData).subscribe((data: any) => {
// 打印最终的资源 URL 地址
console.log(this.token.url + '/' + this.token.key)
})
}
}
复制代码