⚡ Optimize new attachment upload
This commit is contained in:
parent
e9dad009a4
commit
0c4e363d95
@ -37,7 +37,7 @@
|
|||||||
color="white"
|
color="white"
|
||||||
prepend-icon="mdi-launch"
|
prepend-icon="mdi-launch"
|
||||||
text="Open in browser"
|
text="Open in browser"
|
||||||
:href="getAttachmentUrl(item.id)"
|
:href="getAttachmentUrl(item.rid)"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,13 +5,31 @@
|
|||||||
|
|
||||||
<div class="my-5 w-[640px]">
|
<div class="my-5 w-[640px]">
|
||||||
<v-expand-transition>
|
<v-expand-transition>
|
||||||
|
<div v-if="!multipartProgress.value">
|
||||||
<v-file-input
|
<v-file-input
|
||||||
label="File input"
|
label="File input"
|
||||||
variant="solo"
|
variant="solo"
|
||||||
:hide-details="true"
|
:hide-details="true"
|
||||||
v-if="!multipartProgress.value"
|
|
||||||
v-model="content"
|
v-model="content"
|
||||||
></v-file-input>
|
></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>
|
||||||
|
|
||||||
<v-expand-transition>
|
<v-expand-transition>
|
||||||
@ -28,9 +46,9 @@
|
|||||||
|
|
||||||
<v-expand-transition>
|
<v-expand-transition>
|
||||||
<div v-if="success">
|
<div v-if="success">
|
||||||
<div class="mt-3">
|
<v-card class="mt-3">
|
||||||
<attachment-carousel :attachments="[multipartInfo.rid]" />
|
<attachment-carousel :attachments="[multipartInfo.rid]" />
|
||||||
</div>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
</v-expand-transition>
|
</v-expand-transition>
|
||||||
|
|
||||||
@ -62,7 +80,14 @@ useHead({
|
|||||||
|
|
||||||
const { t } = useI18n()
|
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 content = ref<File | null>(null)
|
||||||
|
const pool = ref("interactive")
|
||||||
|
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
const success = ref(false)
|
const success = ref(false)
|
||||||
@ -82,22 +107,30 @@ async function submit() {
|
|||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
|
const limit = 3
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await createMultipartPlaceholder()
|
await createMultipartPlaceholder()
|
||||||
console.log(`[PAPERCLIP] Multipart placeholder has been created with rid ${multipartInfo.value.rid}`)
|
console.log(`[PAPERCLIP] Multipart placeholder has been created with rid ${multipartInfo.value.rid}`)
|
||||||
let taskIdx = 0
|
|
||||||
multipartProgress.value = 0
|
multipartProgress.value = 0
|
||||||
multipartProgress.current = taskIdx
|
multipartProgress.current = 0
|
||||||
if (multipartInfo.value["file_chunks"]) {
|
|
||||||
multipartProgress.total = Object.keys(multipartInfo.value["file_chunks"] ?? {}).length
|
const chunks = Object.keys(multipartInfo.value["file_chunks"] ?? {})
|
||||||
}
|
multipartProgress.total = chunks.length
|
||||||
for (const chunk in multipartInfo.value["file_chunks"]) {
|
|
||||||
|
const uploadChunks = async (chunk: string) => {
|
||||||
await uploadSingleMultipart(chunk)
|
await uploadSingleMultipart(chunk)
|
||||||
taskIdx++
|
multipartProgress.current++
|
||||||
console.log(`[PAPERCLIP] Uploaded multipart ${taskIdx}/${multipartProgress.total}`)
|
console.log(`[PAPERCLIP] Uploaded multipart ${multipartProgress.current}/${multipartProgress.total}`)
|
||||||
multipartProgress.value = taskIdx / multipartProgress.total
|
multipartProgress.value = multipartProgress.current / multipartProgress.total
|
||||||
multipartProgress.current = taskIdx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"]) {
|
if (multipartInfo.value["is_uploaded"]) {
|
||||||
console.log(`[PAPERCLIP] Entire file has been uploaded in ${multipartProgress.total} chunk(s)`)
|
console.log(`[PAPERCLIP] Entire file has been uploaded in ${multipartProgress.total} chunk(s)`)
|
||||||
success.value = true
|
success.value = true
|
||||||
@ -113,6 +146,12 @@ async function submit() {
|
|||||||
async function createMultipartPlaceholder() {
|
async function createMultipartPlaceholder() {
|
||||||
if (!content.value) return
|
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(".")
|
const nameArray = content.value.name.split(".")
|
||||||
nameArray.pop()
|
nameArray.pop()
|
||||||
|
|
||||||
@ -120,10 +159,11 @@ async function createMultipartPlaceholder() {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
pool: "interactive",
|
pool: pool.value,
|
||||||
size: content.value.size,
|
size: content.value.size,
|
||||||
name: content.value.name,
|
name: content.value.name,
|
||||||
alt: nameArray.join("."),
|
alt: nameArray.join("."),
|
||||||
|
mimetype: mimetype,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
if (resp.status != 200) throw new Error(await resp.text())
|
if (resp.status != 200) throw new Error(await resp.text())
|
||||||
|
Loading…
Reference in New Issue
Block a user