mirror of
https://github.com/rustfs/console.git
synced 2026-10-30 19:33:40 +08:00
275 lines
7.4 KiB
TypeScript
275 lines
7.4 KiB
TypeScript
import {
|
|
DeleteObjectCommand,
|
|
DeleteObjectTaggingCommand,
|
|
GetObjectCommand,
|
|
GetObjectLegalHoldCommand,
|
|
GetObjectRetentionCommand,
|
|
GetObjectTaggingCommand,
|
|
HeadObjectCommand,
|
|
ListObjectsV2Command,
|
|
ListObjectVersionsCommand,
|
|
ObjectLockRetentionMode,
|
|
PutObjectCommand,
|
|
PutObjectLegalHoldCommand,
|
|
PutObjectRetentionCommand,
|
|
PutObjectTaggingCommand,
|
|
} from '@aws-sdk/client-s3'
|
|
import { getSignedUrl as _getSignedUrl } from '@aws-sdk/s3-request-presigner'
|
|
|
|
export function useObject({ bucket, region }: { bucket: string; region?: string }) {
|
|
const $client = useNuxtApp().$s3Client
|
|
|
|
const headObject = async (key: string) => {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
}
|
|
|
|
return await $client.send(new HeadObjectCommand(params))
|
|
}
|
|
|
|
const getSignedUrl = async (key: string, expiresIn = 3600) => {
|
|
const command = new GetObjectCommand({
|
|
Bucket: bucket,
|
|
Key: key,
|
|
})
|
|
|
|
return await _getSignedUrl($client, command, { expiresIn })
|
|
}
|
|
|
|
const putObject = async (key: string, body: Blob | string) => {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
Body: body,
|
|
}
|
|
|
|
return await $client.send(new PutObjectCommand(params))
|
|
}
|
|
|
|
const deleteObject = async (key: string, versionId?: string) => {
|
|
const params: {
|
|
Bucket: string
|
|
Key: string
|
|
VersionId?: string
|
|
} = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
}
|
|
|
|
// If version ID exists and is not null version ID, pass the version ID
|
|
if (versionId) {
|
|
params.VersionId = versionId
|
|
}
|
|
|
|
return await $client.send(new DeleteObjectCommand(params))
|
|
}
|
|
|
|
const listObject = async (bucket: string, prefix: string | undefined = undefined, pageSize: number = 25) => {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Prefix: prefix,
|
|
MaxKeys: pageSize,
|
|
Delimiter: '/',
|
|
}
|
|
|
|
return await $client.send(new ListObjectsV2Command(params))
|
|
}
|
|
|
|
async function mapAllFiles(bucketName: string, prefix: string, callback: (fileKey: string) => void) {
|
|
let isTruncated = true
|
|
let continuationToken: string | undefined = undefined
|
|
|
|
while (isTruncated) {
|
|
const params: {
|
|
Bucket: string
|
|
Prefix: string
|
|
ContinuationToken?: string
|
|
} = {
|
|
Bucket: bucketName,
|
|
Prefix: prefix,
|
|
ContinuationToken: continuationToken,
|
|
}
|
|
|
|
try {
|
|
const data = await $client.send(new ListObjectsV2Command(params))
|
|
data.Contents?.forEach(item => {
|
|
if (item.Key) {
|
|
callback(item.Key)
|
|
}
|
|
})
|
|
|
|
isTruncated = data.IsTruncated || false
|
|
continuationToken = data.NextContinuationToken
|
|
} catch (error) {
|
|
console.error('Error listing files: ', error)
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
|
|
async function getObjectInfo(key: string) {
|
|
const [meta, signedUrl] = await Promise.all([headObject(key), getSignedUrl(key)])
|
|
return {
|
|
...meta,
|
|
Key: key,
|
|
SignedUrl: signedUrl,
|
|
}
|
|
}
|
|
|
|
async function getObjectTags(key: string): Promise<Array<{ Key: string; Value: string }>> {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
}
|
|
|
|
const response = await $client.send(new GetObjectTaggingCommand(params))
|
|
return (response.TagSet ?? []).map(tag => ({
|
|
Key: tag.Key ?? '',
|
|
Value: tag.Value ?? '',
|
|
}))
|
|
}
|
|
|
|
async function putObjectTags(key: string, tags: Array<{ Key: string; Value: string }>) {
|
|
const sanitizedTags = tags.filter(tag => tag.Key && tag.Value).map(tag => ({ Key: tag.Key, Value: tag.Value }))
|
|
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
Tagging: {
|
|
TagSet: sanitizedTags,
|
|
},
|
|
}
|
|
|
|
return await $client.send(new PutObjectTaggingCommand(params))
|
|
}
|
|
|
|
async function deleteObjectTags(key: string) {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
}
|
|
|
|
return await $client.send(new DeleteObjectTaggingCommand(params))
|
|
}
|
|
|
|
async function getObjectRetention(key: string) {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
}
|
|
|
|
try {
|
|
const response = await $client.send(new GetObjectRetentionCommand(params))
|
|
const retention = response?.Retention
|
|
if (!retention || Object.keys(retention).length === 0) {
|
|
return { Mode: '', RetainUntilDate: '' }
|
|
}
|
|
return {
|
|
Mode: retention.Mode ?? '',
|
|
RetainUntilDate: retention.RetainUntilDate ? new Date(retention.RetainUntilDate).toISOString() : '',
|
|
}
|
|
} catch (error: any) {
|
|
if (error.message?.includes('Deserialization error')) {
|
|
return { Mode: '', RetainUntilDate: '' }
|
|
}
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async function putObjectRetention(
|
|
key: string,
|
|
retention: { Mode: 'GOVERNANCE' | 'COMPLIANCE'; RetainUntilDate?: string }
|
|
) {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
Retention: {
|
|
Mode: retention.Mode === 'COMPLIANCE' ? ObjectLockRetentionMode.COMPLIANCE : ObjectLockRetentionMode.GOVERNANCE,
|
|
...(retention.RetainUntilDate ? { RetainUntilDate: new Date(retention.RetainUntilDate) } : {}),
|
|
},
|
|
}
|
|
return await $client.send(new PutObjectRetentionCommand(params))
|
|
}
|
|
|
|
async function getObjectLegalHold(key: string) {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
}
|
|
|
|
return await $client.send(new GetObjectLegalHoldCommand(params))
|
|
}
|
|
|
|
async function putObjectLegalHold(key: string, legalHold: any) {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Key: key,
|
|
LegalHold: legalHold,
|
|
}
|
|
|
|
return await $client.send(new PutObjectLegalHoldCommand(params))
|
|
}
|
|
|
|
async function listObjectVersions(key: string) {
|
|
const params = {
|
|
Bucket: bucket,
|
|
Prefix: key, // match "abc" and "abcd"
|
|
Delimiter: '/', // has no effect on "abcd", can keep or remove
|
|
}
|
|
|
|
const res = await $client.send(new ListObjectVersionsCommand(params))
|
|
|
|
const Versions = (res.Versions ?? []).filter(v => v.Key === key)
|
|
const DeleteMarkers = (res.DeleteMarkers ?? []).filter(m => m.Key === key)
|
|
|
|
// Sort by LastModified desc
|
|
Versions.sort((a, b) => +new Date(b.LastModified!) - +new Date(a.LastModified!))
|
|
DeleteMarkers.sort((a, b) => +new Date(b.LastModified!) - +new Date(a.LastModified!))
|
|
|
|
return { ...res, Versions, DeleteMarkers }
|
|
}
|
|
|
|
async function deleteAllVersions(key: string) {
|
|
try {
|
|
// Get all versions of the object
|
|
const versions = await listObjectVersions(key)
|
|
const versionsToDelete = versions.Versions || []
|
|
const deleteMarkers = versions.DeleteMarkers || []
|
|
|
|
// Delete all versions
|
|
const deletePromises = versionsToDelete.map(version => deleteObject(key, version.VersionId))
|
|
|
|
// Delete all delete markers
|
|
const deleteMarkerPromises = deleteMarkers.map(marker => deleteObject(key, marker.VersionId))
|
|
|
|
await Promise.all([...deletePromises, ...deleteMarkerPromises])
|
|
|
|
return { success: true }
|
|
} catch (error) {
|
|
console.error('Error deleting all versions:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
return {
|
|
headObject,
|
|
putObject,
|
|
deleteObject,
|
|
getSignedUrl,
|
|
getObjectInfo,
|
|
mapAllFiles,
|
|
listObject,
|
|
getObjectTags,
|
|
putObjectTags,
|
|
deleteObjectTags,
|
|
getObjectRetention,
|
|
putObjectRetention,
|
|
getObjectLegalHold,
|
|
putObjectLegalHold,
|
|
setLegalHold: (key: string, enabled: boolean) => putObjectLegalHold(key, { Status: enabled ? 'ON' : 'OFF' }),
|
|
listObjectVersions,
|
|
deleteAllVersions,
|
|
}
|
|
}
|