feat: object preview

This commit is contained in:
overtrue
2024-12-19 21:11:11 +08:00
parent 0fdbb1a6c2
commit f77eb2b8cf
6 changed files with 418 additions and 116 deletions
+1
View File
@@ -36,6 +36,7 @@ declare module 'vue' {
NPageHeader: typeof import('naive-ui')['NPageHeader']
NSelect: typeof import('naive-ui')['NSelect']
NSpace: typeof import('naive-ui')['NSpace']
NSpin: typeof import('naive-ui')['NSpin']
NSwitch: typeof import('naive-ui')['NSwitch']
NTabPane: typeof import('naive-ui')['NTabPane']
NTabs: typeof import('naive-ui')['NTabs']
+135
View File
@@ -0,0 +1,135 @@
<template>
<n-modal :show="show" @update:show="val => $emit('update:show', val)" size="huge">
<template #header>
<div style="display:flex; justify-content: space-between; align-items:center;">
<span>对象预览: {{ objectKey }}</span>
<n-button size="small" ghost @click="closeModal">关闭</n-button>
</div>
</template>
<n-card class="max-w-screen-md">
<template #header>
<div class="flex items-center justify-between gap-4 truncate">
<div>
预览内容 <small class="text-gray-300">{{ objectKey }}</small>
</div>
<n-button type="default" size="small" ghost @click="closeModal">
<Icon name="ri:close-line" class="mr-2" />
<span>关闭</span>
</n-button>
</div>
</template>
<n-spin v-if="loading" size="large"></n-spin>
<div v-else class="min-h-64 max-h-[80vh] overflow-y-auto flex-1 flex flex-col justify-center items-center">
<template v-if="canPreview">
<img v-if="isImage" :src="previewUrl" alt="preview" />
<iframe v-else-if="isPdf" :src="previewUrl" class="w-full min-h-[70vh]" frameborder="0"></iframe>
<pre v-else-if="isText" class="w-full">{{ fileContent }}</pre>
<video v-else-if="isVideo" controls class="w-full">
<source :src="previewUrl" type="video/mp4" />
您的浏览器不支持 video 标签
</video>
<audio v-else-if="isAudio" controls class="w-full">
<source :src="previewUrl" type="audio/mpeg" />
您的浏览器不支持 audio 标签
</audio>
</template>
<div v-else class="text-center text-gray-500">
无法预览该对象的内容(MIME类型:{{ contentType }}),请下载查看
</div>
</div>
</n-card>
</n-modal>
</template>
<script setup lang="ts">
import { useMessage } from 'naive-ui'
import { computed, ref, watch } from 'vue'
const props = defineProps<{
show: boolean
bucketName: string
objectKey: string
}>()
const emit = defineEmits(['update:show'])
const { getSignedUrl, headObject } = useObject({ bucket: props.bucketName })
// 内部状态
const previewUrl = ref<string | undefined>(undefined)
const contentType = ref<string | undefined>(undefined)
const fileContent = ref<string | undefined>(undefined)
const loading = ref<boolean>(false)
const message = useMessage()
// MIME 类型判断逻辑
const isImage = computed(() => contentType.value?.startsWith('image/') || false)
const isVideo = computed(() => contentType.value?.startsWith('video/') || false)
const isAudio = computed(() => contentType.value?.startsWith('audio/') || false)
const isPdf = computed(() => contentType.value === 'application/pdf')
const isText = computed(() => {
// 常见文本类型,可按需扩展
return contentType.value?.startsWith('text/') ||
contentType.value === 'application/json' ||
contentType.value === 'application/xml' || false
})
const canPreview = computed(() => isImage.value || isPdf.value || isText.value || isVideo.value || isAudio.value)
// 当 show 为 true 时触发加载逻辑
watch(() => props.show, async (newVal) => {
if (newVal) {
await loadPreview()
} else {
resetState()
}
})
async function loadPreview() {
loading.value = true
previewUrl.value = undefined
fileContent.value = undefined
contentType.value = undefined
try {
// 获取预签名URL
const url = await getSignedUrl(objectKey.value)
previewUrl.value = url
// 先使用 HEAD 请求获取 Content-Type
const response = await headObject(objectKey.value)
const ctype = response?.ContentType
contentType.value = ctype || 'application/octet-stream'
// 根据 MIME 类型决定是否加载内容
if (isText.value) {
// 加载文本内容
const response = await fetch(url)
const text = await response.text()
fileContent.value = text
}
} catch (err) {
console.error(err)
message.error('获取对象预览失败')
closeModal()
} finally {
loading.value = false
}
}
function resetState() {
previewUrl.value = undefined
fileContent.value = undefined
contentType.value = undefined
loading.value = false
}
function closeModal() {
emit('update:show', false)
}
const objectKey = computed(() => props.objectKey)
</script>
+28 -14
View File
@@ -5,15 +5,15 @@
</template>
<template #extra>
<div class="flex items-center gap-4 ml-auto">
<n-button>
<n-button @click="() => download()">
<Icon name="ri:download-line" class="mr-2" />
<span>下载</span>
</n-button>
<n-button>
<n-button @click="() => copySignedUrl()">
<Icon name="ri:file-copy-line" class="mr-2" />
<span>复制临时链接</span>
</n-button>
<n-button>
<n-button @click="() => showPreview = true">
<Icon name="ri:eye-line" class="mr-2" />
<span>预览</span>
</n-button>
@@ -29,6 +29,9 @@
</template>
</n-page-header>
<n-card title="对象信息">
<div v-if="status === 'pending'" class="flex items-center justify-center">
<n-spin size="small" />
</div>
<n-descriptions :column="1">
<n-descriptions-item label="对象名称">{{ key }}</n-descriptions-item>
<n-descriptions-item label="对象大小">{{ object?.ContentLength }}</n-descriptions-item>
@@ -37,18 +40,19 @@
<n-descriptions-item label="ETag">{{ object?.ETag }}</n-descriptions-item>
<n-descriptions-item label="最后修改时间">{{ object?.LastModified }}</n-descriptions-item>
</n-descriptions>
<object-preview-modal v-model:show="showPreview" :bucketName="bucketName" :objectKey="key" />
</n-card>
</template>
<script setup lang="ts">
import { useAsyncData } from '#app'
import { HeadObjectCommand, type HeadObjectCommandOutput } from '@aws-sdk/client-s3'
import { computed } from 'vue'
const router = useRouter()
const { $s3Client } = useNuxtApp();
const message = useMessage();
const props = defineProps<{ bucket: string; objectKey: string }>()
const bucketName = computed(() => props.bucket as string)
@@ -56,18 +60,28 @@ const bucketName = computed(() => props.bucket as string)
// 当前路径的前缀, example: '/folder1/folder2/'
const key = computed(() => decodeURIComponent(props.objectKey as string))
// 预览内容
const showPreview = ref(false)
const objectApi = useObject({ bucket: bucketName.value });
// 在服务端获取数据
const { data: object, refresh } = await useAsyncData<HeadObjectCommandOutput>(`object-detail&${key}`, async () => {
const params = {
Bucket: bucketName.value,
Key: key.value
}
const { data: object, status, refresh } = useAsyncData(`head-object&${key}`, () => objectApi.headObject(key.value))
return await $s3Client.send(new HeadObjectCommand(params))
})
console.log(object);
const download = async () => {
const msg = message.loading('正在获取下载链接...');
const url = await objectApi.getSignedUrl(key.value);
msg.destroy();
window.open(url, '_blank')
}
const copySignedUrl = async () => {
const msg = message.loading('正在获取下载链接...');
const url = await objectApi.getSignedUrl(key.value);
await navigator.clipboard.writeText(url);
msg.destroy();
message.success('链接已复制到剪贴板');
}
</script>
+26
View File
@@ -0,0 +1,26 @@
import { GetObjectCommand, HeadObjectCommand } 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 })
}
return { headObject, getSignedUrl }
}
+227 -102
View File
@@ -8,6 +8,7 @@
"hasInstallScript": true,
"dependencies": {
"@aws-sdk/client-s3": "^3.705.0",
"@aws-sdk/s3-request-presigner": "^3.715.0",
"@nuxt/icon": "^1.9.1",
"@nuxtjs/i18n": "^9.1.1",
"@nuxtjs/tailwindcss": "^6.12.2",
@@ -859,6 +860,102 @@
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/s3-request-presigner": {
"version": "3.715.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.715.0.tgz",
"integrity": "sha512-zdstGtX42eUCAyXKkhwJNZx7f5KMJ0diPu8ToSfh1NJxNL+8j5ntRQXf0QOMRh67wHBcereiQe0Va0h7n9PnJw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/signature-v4-multi-region": "3.714.0",
"@aws-sdk/types": "3.714.0",
"@aws-sdk/util-format-url": "3.714.0",
"@smithy/middleware-endpoint": "^3.2.5",
"@smithy/protocol-http": "^4.1.8",
"@smithy/smithy-client": "^3.5.0",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/core": {
"version": "3.714.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.714.0.tgz",
"integrity": "sha512-TlZ50d8MEPVp9O03SvisOmcmxjxhMDKHJJcrBgYjgDej6QmNfiFwtCRkReXDdkEeXP29ehMs7uPXtmVvPqziYw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.714.0",
"@smithy/core": "^2.5.5",
"@smithy/node-config-provider": "^3.1.12",
"@smithy/property-provider": "^3.1.11",
"@smithy/protocol-http": "^4.1.8",
"@smithy/signature-v4": "^4.2.4",
"@smithy/smithy-client": "^3.5.0",
"@smithy/types": "^3.7.2",
"@smithy/util-middleware": "^3.0.11",
"fast-xml-parser": "4.4.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/middleware-sdk-s3": {
"version": "3.714.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.714.0.tgz",
"integrity": "sha512-YYhX+JefwwEsUxYs0YXn5Mfb97Lo3hwnk3qRIlUkcotCsHYwgCX4jVWjeh8HK+RFFx3Krbh/8/YmzTkI/Z4Z9Q==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/core": "3.714.0",
"@aws-sdk/types": "3.714.0",
"@aws-sdk/util-arn-parser": "3.693.0",
"@smithy/core": "^2.5.5",
"@smithy/node-config-provider": "^3.1.12",
"@smithy/protocol-http": "^4.1.8",
"@smithy/signature-v4": "^4.2.4",
"@smithy/smithy-client": "^3.5.0",
"@smithy/types": "^3.7.2",
"@smithy/util-config-provider": "^3.0.0",
"@smithy/util-middleware": "^3.0.11",
"@smithy/util-stream": "^3.3.2",
"@smithy/util-utf8": "^3.0.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/signature-v4-multi-region": {
"version": "3.714.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.714.0.tgz",
"integrity": "sha512-xIQyx0ILRtJZnSUPpMsWkwASuFDYh9GPnr7p+pmfsV5KtRQluHuoH1wPkPTeNuTnAl7RDHUOmcOgTPUCDxiKxg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/middleware-sdk-s3": "3.714.0",
"@aws-sdk/types": "3.714.0",
"@smithy/protocol-http": "^4.1.8",
"@smithy/signature-v4": "^4.2.4",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/s3-request-presigner/node_modules/@aws-sdk/types": {
"version": "3.714.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz",
"integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/signature-v4-multi-region": {
"version": "3.696.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.696.0.tgz",
@@ -935,6 +1032,34 @@
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/util-format-url": {
"version": "3.714.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.714.0.tgz",
"integrity": "sha512-PA/ES6BeKmYzFOsZ3az/8MqSLf6uzXAS7GsYONZMF6YASn4ewd/AspuvQMp6+x9VreAPCq7PecF+XL9KXejtPg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.714.0",
"@smithy/querystring-builder": "^3.0.11",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/util-format-url/node_modules/@aws-sdk/types": {
"version": "3.714.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz",
"integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@aws-sdk/util-locate-window": {
"version": "3.693.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz",
@@ -4138,12 +4263,12 @@
}
},
"node_modules/@smithy/abort-controller": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.8.tgz",
"integrity": "sha512-+3DOBcUn5/rVjlxGvUPKc416SExarAQ+Qe0bqk30YSUjbepwpS7QN0cyKUSifvLJhdMZ0WPzPP5ymut0oonrpQ==",
"version": "3.1.9",
"resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.9.tgz",
"integrity": "sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4186,17 +4311,17 @@
}
},
"node_modules/@smithy/core": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.4.tgz",
"integrity": "sha512-iFh2Ymn2sCziBRLPuOOxRPkuCx/2gBdXtBGuCUFLUe6bWYjKnhHyIPqGeNkLZ5Aco/5GjebRTBFiWID3sDbrKw==",
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.5.tgz",
"integrity": "sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/middleware-serde": "^3.0.10",
"@smithy/protocol-http": "^4.1.7",
"@smithy/types": "^3.7.1",
"@smithy/middleware-serde": "^3.0.11",
"@smithy/protocol-http": "^4.1.8",
"@smithy/types": "^3.7.2",
"@smithy/util-body-length-browser": "^3.0.0",
"@smithy/util-middleware": "^3.0.10",
"@smithy/util-stream": "^3.3.1",
"@smithy/util-middleware": "^3.0.11",
"@smithy/util-stream": "^3.3.2",
"@smithy/util-utf8": "^3.0.0",
"tslib": "^2.6.2"
},
@@ -4288,14 +4413,14 @@
}
},
"node_modules/@smithy/fetch-http-handler": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.1.tgz",
"integrity": "sha512-bH7QW0+JdX0bPBadXt8GwMof/jz0H28I84hU1Uet9ISpzUqXqRQ3fEZJ+ANPOhzSEczYvANNl3uDQDYArSFDtA==",
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz",
"integrity": "sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/protocol-http": "^4.1.7",
"@smithy/querystring-builder": "^3.0.10",
"@smithy/types": "^3.7.1",
"@smithy/protocol-http": "^4.1.8",
"@smithy/querystring-builder": "^3.0.11",
"@smithy/types": "^3.7.2",
"@smithy/util-base64": "^3.0.0",
"tslib": "^2.6.2"
}
@@ -4389,18 +4514,18 @@
}
},
"node_modules/@smithy/middleware-endpoint": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.4.tgz",
"integrity": "sha512-TybiW2LA3kYVd3e+lWhINVu1o26KJbBwOpADnf0L4x/35vLVica77XVR5hvV9+kWeTGeSJ3IHTcYxbRxlbwhsg==",
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz",
"integrity": "sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/core": "^2.5.4",
"@smithy/middleware-serde": "^3.0.10",
"@smithy/node-config-provider": "^3.1.11",
"@smithy/shared-ini-file-loader": "^3.1.11",
"@smithy/types": "^3.7.1",
"@smithy/url-parser": "^3.0.10",
"@smithy/util-middleware": "^3.0.10",
"@smithy/core": "^2.5.5",
"@smithy/middleware-serde": "^3.0.11",
"@smithy/node-config-provider": "^3.1.12",
"@smithy/shared-ini-file-loader": "^3.1.12",
"@smithy/types": "^3.7.2",
"@smithy/url-parser": "^3.0.11",
"@smithy/util-middleware": "^3.0.11",
"tslib": "^2.6.2"
},
"engines": {
@@ -4428,12 +4553,12 @@
}
},
"node_modules/@smithy/middleware-serde": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.10.tgz",
"integrity": "sha512-MnAuhh+dD14F428ubSJuRnmRsfOpxSzvRhaGVTvd/lrUDE3kxzCCmH8lnVTvoNQnV2BbJ4c15QwZ3UdQBtFNZA==",
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz",
"integrity": "sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4441,12 +4566,12 @@
}
},
"node_modules/@smithy/middleware-stack": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.10.tgz",
"integrity": "sha512-grCHyoiARDBBGPyw2BeicpjgpsDFWZZxptbVKb3CRd/ZA15F/T6rZjCCuBUjJwdck1nwUuIxYtsS4H9DDpbP5w==",
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz",
"integrity": "sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4454,14 +4579,14 @@
}
},
"node_modules/@smithy/node-config-provider": {
"version": "3.1.11",
"resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.11.tgz",
"integrity": "sha512-URq3gT3RpDikh/8MBJUB+QGZzfS7Bm6TQTqoh4CqE8NBuyPkWa5eUXj0XFcFfeZVgg3WMh1u19iaXn8FvvXxZw==",
"version": "3.1.12",
"resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz",
"integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/property-provider": "^3.1.10",
"@smithy/shared-ini-file-loader": "^3.1.11",
"@smithy/types": "^3.7.1",
"@smithy/property-provider": "^3.1.11",
"@smithy/shared-ini-file-loader": "^3.1.12",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4469,15 +4594,15 @@
}
},
"node_modules/@smithy/node-http-handler": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.1.tgz",
"integrity": "sha512-fr+UAOMGWh6bn4YSEezBCpJn9Ukp9oR4D32sCjCo7U81evE11YePOQ58ogzyfgmjIO79YeOdfXXqr0jyhPQeMg==",
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz",
"integrity": "sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/abort-controller": "^3.1.8",
"@smithy/protocol-http": "^4.1.7",
"@smithy/querystring-builder": "^3.0.10",
"@smithy/types": "^3.7.1",
"@smithy/abort-controller": "^3.1.9",
"@smithy/protocol-http": "^4.1.8",
"@smithy/querystring-builder": "^3.0.11",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4485,12 +4610,12 @@
}
},
"node_modules/@smithy/property-provider": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.10.tgz",
"integrity": "sha512-n1MJZGTorTH2DvyTVj+3wXnd4CzjJxyXeOgnTlgNVFxaaMeT4OteEp4QrzF8p9ee2yg42nvyVK6R/awLCakjeQ==",
"version": "3.1.11",
"resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
"integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4498,12 +4623,12 @@
}
},
"node_modules/@smithy/protocol-http": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.7.tgz",
"integrity": "sha512-FP2LepWD0eJeOTm0SjssPcgqAlDFzOmRXqXmGhfIM52G7Lrox/pcpQf6RP4F21k0+O12zaqQt5fCDOeBtqY6Cg==",
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz",
"integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4511,12 +4636,12 @@
}
},
"node_modules/@smithy/querystring-builder": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.10.tgz",
"integrity": "sha512-nT9CQF3EIJtIUepXQuBFb8dxJi3WVZS3XfuDksxSCSn+/CzZowRLdhDn+2acbBv8R6eaJqPupoI/aRFIImNVPQ==",
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz",
"integrity": "sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"@smithy/util-uri-escape": "^3.0.0",
"tslib": "^2.6.2"
},
@@ -4525,12 +4650,12 @@
}
},
"node_modules/@smithy/querystring-parser": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.10.tgz",
"integrity": "sha512-Oa0XDcpo9SmjhiDD9ua2UyM3uU01ZTuIrNdZvzwUTykW1PM8o2yJvMh1Do1rY5sUQg4NDV70dMi0JhDx4GyxuQ==",
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz",
"integrity": "sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4550,12 +4675,12 @@
}
},
"node_modules/@smithy/shared-ini-file-loader": {
"version": "3.1.11",
"resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.11.tgz",
"integrity": "sha512-AUdrIZHFtUgmfSN4Gq9nHu3IkHMa1YDcN+s061Nfm+6pQ0mJy85YQDB0tZBCmls0Vuj22pLwDPmL92+Hvfwwlg==",
"version": "3.1.12",
"resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz",
"integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4563,16 +4688,16 @@
}
},
"node_modules/@smithy/signature-v4": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.3.tgz",
"integrity": "sha512-pPSQQ2v2vu9vc8iew7sszLd0O09I5TRc5zhY71KA+Ao0xYazIG+uLeHbTJfIWGO3BGVLiXjUr3EEeCcEQLjpWQ==",
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.4.tgz",
"integrity": "sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^3.0.0",
"@smithy/protocol-http": "^4.1.7",
"@smithy/types": "^3.7.1",
"@smithy/protocol-http": "^4.1.8",
"@smithy/types": "^3.7.2",
"@smithy/util-hex-encoding": "^3.0.0",
"@smithy/util-middleware": "^3.0.10",
"@smithy/util-middleware": "^3.0.11",
"@smithy/util-uri-escape": "^3.0.0",
"@smithy/util-utf8": "^3.0.0",
"tslib": "^2.6.2"
@@ -4582,17 +4707,17 @@
}
},
"node_modules/@smithy/smithy-client": {
"version": "3.4.5",
"resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.4.5.tgz",
"integrity": "sha512-k0sybYT9zlP79sIKd1XGm4TmK0AS1nA2bzDHXx7m0nGi3RQ8dxxQUs4CPkSmQTKAo+KF9aINU3KzpGIpV7UoMw==",
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.5.0.tgz",
"integrity": "sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/core": "^2.5.4",
"@smithy/middleware-endpoint": "^3.2.4",
"@smithy/middleware-stack": "^3.0.10",
"@smithy/protocol-http": "^4.1.7",
"@smithy/types": "^3.7.1",
"@smithy/util-stream": "^3.3.1",
"@smithy/core": "^2.5.5",
"@smithy/middleware-endpoint": "^3.2.5",
"@smithy/middleware-stack": "^3.0.11",
"@smithy/protocol-http": "^4.1.8",
"@smithy/types": "^3.7.2",
"@smithy/util-stream": "^3.3.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4600,9 +4725,9 @@
}
},
"node_modules/@smithy/types": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.1.tgz",
"integrity": "sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA==",
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz",
"integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -4612,13 +4737,13 @@
}
},
"node_modules/@smithy/url-parser": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.10.tgz",
"integrity": "sha512-j90NUalTSBR2NaZTuruEgavSdh8MLirf58LoGSk4AtQfyIymogIhgnGUU2Mga2bkMkpSoC9gxb74xBXL5afKAQ==",
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.11.tgz",
"integrity": "sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/querystring-parser": "^3.0.10",
"@smithy/types": "^3.7.1",
"@smithy/querystring-parser": "^3.0.11",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
}
},
@@ -4743,12 +4868,12 @@
}
},
"node_modules/@smithy/util-middleware": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.10.tgz",
"integrity": "sha512-eJO+/+RsrG2RpmY68jZdwQtnfsxjmPxzMlQpnHKjFPwrYqvlcT+fHdT+ZVwcjlWSrByOhGr9Ff2GG17efc192A==",
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz",
"integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/types": "^3.7.1",
"@smithy/types": "^3.7.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -4770,14 +4895,14 @@
}
},
"node_modules/@smithy/util-stream": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.1.tgz",
"integrity": "sha512-Ff68R5lJh2zj+AUTvbAU/4yx+6QPRzg7+pI7M1FbtQHcRIp7xvguxVsQBKyB3fwiOwhAKu0lnNyYBaQfSW6TNw==",
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.2.tgz",
"integrity": "sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/fetch-http-handler": "^4.1.1",
"@smithy/node-http-handler": "^3.3.1",
"@smithy/types": "^3.7.1",
"@smithy/fetch-http-handler": "^4.1.2",
"@smithy/node-http-handler": "^3.3.2",
"@smithy/types": "^3.7.2",
"@smithy/util-base64": "^3.0.0",
"@smithy/util-buffer-from": "^3.0.0",
"@smithy/util-hex-encoding": "^3.0.0",
+1
View File
@@ -11,6 +11,7 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3.705.0",
"@aws-sdk/s3-request-presigner": "^3.715.0",
"@nuxt/icon": "^1.9.1",
"@nuxtjs/i18n": "^9.1.1",
"@nuxtjs/tailwindcss": "^6.12.2",