Optimize new attachment upload

This commit is contained in:
LittleSheep 2024-08-22 01:26:32 +08:00
parent e9dad009a4
commit 0c4e363d95
2 changed files with 61 additions and 21 deletions

View File

@ -37,7 +37,7 @@
color="white"
prepend-icon="mdi-launch"
text="Open in browser"
:href="getAttachmentUrl(item.id)"
:href="getAttachmentUrl(item.rid)"
target="_blank"
/>
</div>

View File

@ -5,13 +5,31 @@
<div class="my-5 w-[640px]">
<v-expand-transition>
<div v-if="!multipartProgress.value">
<v-file-input
label="File input"
variant="solo"
:hide-details="true"
v-if="!multipartProgress.value"
v-model="content"
></v-file-input>
<v-select
label="Storage pool"
variant="underlined"
:items="poolOptions"
item-title="label"
item-value="value"
density="comfortable"
prepend-icon="mdi-database"
:hide-details="true"
class="mt-5"
v-model="pool"
>
<template v-slot:item="{ props, item }">
<v-list-item v-bind="props" :subtitle="item.raw.description" :disabled="item.raw.disabled" />
</template>
</v-select>
</div>
</v-expand-transition>
<v-expand-transition>
@ -28,9 +46,9 @@
<v-expand-transition>
<div v-if="success">
<div class="mt-3">
<v-card class="mt-3">
<attachment-carousel :attachments="[multipartInfo.rid]" />
</div>
</v-card>
</div>
</v-expand-transition>
@ -62,7 +80,14 @@ useHead({
const { t } = useI18n()
const poolOptions = [
{ label: "Interactive", description: "Public indexable, no lifecycle.", value: "interactive" },
{ label: "Messaging", description: "Has lifecycle, will delete after 14 days.", value: "messaging" },
{ label: "Dedicated Pool", description: "Your own configuration, coming soon.", value: "dedicated", disabled: true },
]
const content = ref<File | null>(null)
const pool = ref("interactive")
const error = ref<string | null>(null)
const success = ref(false)
@ -82,22 +107,30 @@ async function submit() {
loading.value = true
const limit = 3
try {
await createMultipartPlaceholder()
console.log(`[PAPERCLIP] Multipart placeholder has been created with rid ${multipartInfo.value.rid}`)
let taskIdx = 0
multipartProgress.value = 0
multipartProgress.current = taskIdx
if (multipartInfo.value["file_chunks"]) {
multipartProgress.total = Object.keys(multipartInfo.value["file_chunks"] ?? {}).length
}
for (const chunk in multipartInfo.value["file_chunks"]) {
multipartProgress.current = 0
const chunks = Object.keys(multipartInfo.value["file_chunks"] ?? {})
multipartProgress.total = chunks.length
const uploadChunks = async (chunk: string) => {
await uploadSingleMultipart(chunk)
taskIdx++
console.log(`[PAPERCLIP] Uploaded multipart ${taskIdx}/${multipartProgress.total}`)
multipartProgress.value = taskIdx / multipartProgress.total
multipartProgress.current = taskIdx
multipartProgress.current++
console.log(`[PAPERCLIP] Uploaded multipart ${multipartProgress.current}/${multipartProgress.total}`)
multipartProgress.value = multipartProgress.current / multipartProgress.total
}
for (let i = 0; i < chunks.length; i += limit) {
const chunkSlice = chunks.slice(i, i + limit)
await Promise.all(chunkSlice.map(uploadChunks))
}
if (multipartInfo.value["is_uploaded"]) {
console.log(`[PAPERCLIP] Entire file has been uploaded in ${multipartProgress.total} chunk(s)`)
success.value = true
@ -113,6 +146,12 @@ async function submit() {
async function createMultipartPlaceholder() {
if (!content.value) return
const mimetypeMap: { [id: string]: string } = {
"mp4": "video/mp4",
"mov": "video/quicktime",
}
const mimetype = mimetypeMap[content.value.name.split(".").pop() as string]
const nameArray = content.value.name.split(".")
nameArray.pop()
@ -120,10 +159,11 @@ async function createMultipartPlaceholder() {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
pool: "interactive",
pool: pool.value,
size: content.value.size,
name: content.value.name,
alt: nameArray.join("."),
mimetype: mimetype,
}),
})
if (resp.status != 200) throw new Error(await resp.text())