Drive
AdonisJS Drive(@adonisjs/drive)是基于 flydrive.dev 的轻量级封装。FlyDrive 是一个 Node.js 文件存储库,它提供了统一的 API 来与本地文件系统和云存储解决方案(如 S3、R2 和 GCS)交互。
使用 FlyDrive,您可以在各种云存储服务(包括本地文件系统)上管理用户上传的文件,而无需更改任何一行代码。
安装
使用以下命令安装和配置 @adonisjs/drive 包:
node ace add @adonisjs/drive:::disclosure
使用检测到的包管理器安装
@adonisjs/drive包。在
adonisrc.ts文件中注册以下服务提供者。ts{ providers: [ // ...其他 providers () => import('@adonisjs/drive/drive_provider'), ] }创建
config/drive.ts文件。为所选存储服务定义环境变量。
为所选存储服务安装所需的对等依赖。
:::
配置
@adonisjs/drive 包配置存储在 config/drive.ts 文件中。您可以在单个配置文件中定义多个服务的配置。
另请参阅:配置模板
import env from '#start/env'
import app from '@adonisjs/core/services/app'
import { defineConfig, services } from '@adonisjs/drive'
const driveConfig = defineConfig({
default: env.get('DRIVE_DISK'),
services: {
/**
* 在本地文件系统上持久化文件
*/
fs: services.fs({
location: app.makePath('storage'),
serveFiles: true,
routeBasePath: '/uploads',
visibility: 'public',
}),
/**
* 在 Digital Ocean spaces 上持久化文件
*/
spaces: services.s3({
credentials: {
accessKeyId: env.get('SPACES_KEY'),
secretAccessKey: env.get('SPACES_SECRET'),
},
region: env.get('SPACES_REGION'),
bucket: env.get('SPACES_BUCKET'),
endpoint: env.get('SPACES_ENDPOINT'),
visibility: 'public',
}),
},
})
export default driveConfig环境变量
存储服务的凭据/设置作为环境变量存储在 .env 文件中。确保在使用 Drive 之前更新这些值。
此外,DRIVE_DISK 环境变量定义了管理文件的默认磁盘/服务。例如,您可能希望在开发中使用 fs 磁盘,在生产中使用 spaces 磁盘。
使用
配置好 Drive 后,您可以导入 drive 服务与其 API 交互。在以下示例中,我们使用 Drive 处理文件上传操作。
TIP
由于 AdonisJS 集成是 FlyDrive 上的薄层封装,您应该阅读 FlyDrive 文档以更好地理解其 API。
import { cuid } from '@adonisjs/core/helpers'
import drive from '@adonisjs/drive/services/main'
import router from '@adonisjs/core/services/router'
router.put('/me', async ({ request, response }) => {
/**
* 步骤 1:从请求中获取图片并执行基本验证
*/
const image = request.file('avatar', {
size: '2mb',
extnames: ['jpeg', 'jpg', 'png'],
})
if (!image) {
return response.badRequest({ error: 'Image missing' })
}
/**
* 步骤 2:使用 Drive 将图片移动到唯一名称
*/
const key = `uploads/${cuid()}.${image.extname}`
// highlight-start
await image.moveToDisk(key)
// highlight-end
/**
* 使用文件的公共 URL 响应
*/
return {
message: 'Image uploaded',
// highlight-start
url: image.meta.url,
// highlight-end
}
})Drive 包为 MultipartFile 添加了
moveToDisk方法。此方法将文件从其tmpPath移动到配置的存储提供者。移动文件后,文件对象上将设置
meta.url属性。此属性包含文件的公共 URL。如果您的文件是私有的,则必须使用drive.use().getSignedUrl()方法。
Drive 服务
从 @adonisjs/drive/services/main 路径导出的 Drive 服务是使用从 config/drive.ts 文件导出的配置创建的 DriveManager 类的单例实例。
您可以导入此服务与 DriveManager 和配置的文件存储服务交互。例如:
import drive from '@adonisjs/drive/services/main'
drive instanceof DriveManager // true
/**
* 返回默认磁盘的实例
*/
const disk = drive.use()
/**
* 返回名为 r2 的磁盘实例
*/
const disk = drive.use('r2')
/**
* 返回名为 spaces 的磁盘实例
*/
const disk = drive.use('spaces')一旦您获得了 Disk 实例,就可以使用它来管理文件。
另请参阅:Disk API
await disk.put(key, value)
await disk.putStream(key, readableStream)
await disk.get(key)
await disk.getStream(key)
await disk.getArrayBuffer(key)
await disk.delete(key)
await disk.deleteAll(prefix)
await disk.copy(source, destination)
await disk.move(source, destination)
await disk.copyFromFs(source, destination)
await disk.moveFromFs(source, destination)本地文件系统驱动
AdonisJS 集成增强了 FlyDrive 的本地文件系统驱动,并添加了 URL 生成支持和使用 AdonisJS HTTP 服务器提供文件的功能。
以下是配置文件系统驱动可用选项的列表。
{
services: {
fs: services.fs({
location: app.makePath('storage'),
visibility: 'public',
appUrl: env.get('APP_URL'),
serveFiles: true,
routeBasePath: '/uploads',
}),
}
}location
location属性定义应存储文件的目录。应将此目录添加到.gitignore,以便您不会将开发期间上传的文件推送到生产服务器。visibility
visibility属性用于将文件标记为公开或私有。私有文件只能使用签名 URL 访问。了解更多serveFiles
serveFiles选项自动注册路由以从本地文件系统提供文件。您可以使用 list:routes ace 命令查看此路由。routeBasePath
routeBasePath选项定义提供文件路由的基础前缀。确保基础前缀是唯一的。appUrl
您可以选择定义
appUrl属性以创建带有应用程序完整域名的 URL。否则将创建相对 URL。
Edge 助手
在 Edge 模板中,您可以使用以下助手方法之一生成 URL。这两个方法都是异步的,所以确保 await 它们。
<img src="{{ await driveUrl(user.avatar) }}" />
<!-- 为命名磁盘生成 URL -->
<img src="{{ await driveUrl(user.avatar, 's3') }}" />
<img src="{{ await driveUrl(user.avatar, 'r2') }}" /><a href="{{ await driveSignedUrl(invoice.key) }}">
下载发票
</a>
<!-- 为命名磁盘生成 URL -->
<a href="{{ await driveSignedUrl(invoice.key, 's3') }}">
下载发票
</a>
<!-- 使用签名选项生成 URL -->
<a href="{{ await driveSignedUrl(invoice.key, {
expiresIn: '30 mins',
}) }}">
下载发票
</a>MultipartFile 助手
Drive 扩展了 Bodyparser MultipartFile 类并添加了 moveToDisk 方法。此方法将文件从其 tmpPath 复制到配置的存储提供者。
const image = request.file('image')!
const key = 'user-1-avatar.png'
/**
* 将文件移动到默认磁盘
*/
await image.moveToDisk(key)
/**
* 将文件移动到命名磁盘
*/
await image.moveToDisk(key, 's3')
/**
* 在移动操作期间定义其他属性
*/
await image.moveToDisk(key, 's3', {
contentType: 'image/png',
})
/**
* 通过先将文件读取为缓冲区来写入文件。当您的云存储提供者
* 使用"stream"选项导致文件损坏时,可以使用此选项
*/
await image.moveToDisk(key, 's3', {
moveAs: 'buffer'
})测试期间伪造磁盘
Drive 的伪造 API 可在测试期间使用,以防止与远程存储交互。在伪造模式下,drive.use() 方法将返回一个伪造磁盘(由本地文件系统支持),所有文件将写入应用程序根目录的 ./tmp/drive-fakes 目录。
使用 drive.restore 方法恢复伪造后,这些文件会自动删除。
另请参阅:FlyDrive 伪造文档
// title: tests/functional/users/update.spec.ts
import { test } from '@japa/runner'
import drive from '@adonisjs/drive/services/main'
import fileGenerator from '@poppinss/file-generator'
test.group('Users | update', () => {
test('should be able to update my avatar', async ({ client, cleanup }) => {
/**
* 伪造 "spaces" 磁盘并在测试完成后恢复伪造
*/
const fakeDisk = drive.fake('spaces')
cleanup(() => drive.restore('spaces'))
/**
* 创建用户以执行登录和更新
*/
const user = await UserFactory.create()
/**
* 生成一个大小为 1mb 的内存中伪造 png 文件
*/
const { contents, mime, name } = await fileGenerator.generatePng('1mb')
/**
* 发出 put 请求并发送文件
*/
await client
.put('me')
.file('avatar', contents, {
filename: name,
contentType: mime,
})
.loginAs(user)
/**
* 断言文件存在
*/
fakeDisk.assertExists(user.avatar)
})
})