Improve drive downloading (#4523)
* Improve drive file downloading * fix name * wtf crlf * semicolon
This commit is contained in:
parent
d38fc490ad
commit
de47a17be7
|
@ -77,6 +77,7 @@
|
||||||
"@types/qrcode": "1.3.0",
|
"@types/qrcode": "1.3.0",
|
||||||
"@types/ratelimiter": "2.1.28",
|
"@types/ratelimiter": "2.1.28",
|
||||||
"@types/redis": "2.8.10",
|
"@types/redis": "2.8.10",
|
||||||
|
"@types/rename": "1.0.1",
|
||||||
"@types/request": "2.48.1",
|
"@types/request": "2.48.1",
|
||||||
"@types/request-promise-native": "1.0.15",
|
"@types/request-promise-native": "1.0.15",
|
||||||
"@types/request-stats": "3.0.0",
|
"@types/request-stats": "3.0.0",
|
||||||
|
@ -193,6 +194,7 @@
|
||||||
"recaptcha-promise": "0.1.3",
|
"recaptcha-promise": "0.1.3",
|
||||||
"reconnecting-websocket": "4.1.10",
|
"reconnecting-websocket": "4.1.10",
|
||||||
"redis": "2.8.0",
|
"redis": "2.8.0",
|
||||||
|
"rename": "1.0.4",
|
||||||
"request": "2.88.0",
|
"request": "2.88.0",
|
||||||
"request-promise-native": "1.0.7",
|
"request-promise-native": "1.0.7",
|
||||||
"request-stats": "3.0.0",
|
"request-stats": "3.0.0",
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<p @click="click(item)"><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}</p>
|
<p @click="click(item)"><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}</p>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="item.type == 'link'">
|
<template v-else-if="item.type == 'link'">
|
||||||
<a :href="item.href" :target="item.target" @click="click(item)"><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}</a>
|
<a :href="item.href" :target="item.target" @click="click(item)" :download="item.download"><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}</a>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="item.type == 'nest'">
|
<template v-else-if="item.type == 'nest'">
|
||||||
<p><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}...<span class="caret"><fa icon="caret-right"/></span></p>
|
<p><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}...<span class="caret"><fa icon="caret-right"/></span></p>
|
||||||
|
|
|
@ -38,6 +38,7 @@ import anime from 'animejs';
|
||||||
import copyToClipboard from '../../../common/scripts/copy-to-clipboard';
|
import copyToClipboard from '../../../common/scripts/copy-to-clipboard';
|
||||||
import updateAvatar from '../../api/update-avatar';
|
import updateAvatar from '../../api/update-avatar';
|
||||||
import updateBanner from '../../api/update-banner';
|
import updateBanner from '../../api/update-banner';
|
||||||
|
import { appendQuery } from '../../../../../prelude/url';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('desktop/views/components/drive.file.vue'),
|
i18n: i18n('desktop/views/components/drive.file.vue'),
|
||||||
|
@ -88,9 +89,10 @@ export default Vue.extend({
|
||||||
action: this.copyUrl
|
action: this.copyUrl
|
||||||
}, {
|
}, {
|
||||||
type: 'link',
|
type: 'link',
|
||||||
href: `${this.file.url}?download`,
|
href: appendQuery(this.file.url, 'download'),
|
||||||
text: this.$t('contextmenu.download'),
|
text: this.$t('contextmenu.download'),
|
||||||
icon: 'download',
|
icon: 'download',
|
||||||
|
download: this.file.name
|
||||||
}, null, {
|
}, null, {
|
||||||
type: 'item',
|
type: 'item',
|
||||||
text: this.$t('@.delete'),
|
text: this.$t('@.delete'),
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<div>
|
<div>
|
||||||
<ui-input readonly :value="file.url">URL</ui-input>
|
<ui-input readonly :value="file.url">URL</ui-input>
|
||||||
<ui-button link :href="`${file.url}?download`" :download="file.name"><fa icon="download"/> {{ $t('download') }}</ui-button>
|
<ui-button link :href="dlUrl" :download="file.name"><fa icon="download"/> {{ $t('download') }}</ui-button>
|
||||||
<ui-button @click="rename"><fa icon="pencil-alt"/> {{ $t('rename') }}</ui-button>
|
<ui-button @click="rename"><fa icon="pencil-alt"/> {{ $t('rename') }}</ui-button>
|
||||||
<ui-button @click="move"><fa :icon="['far', 'folder-open']"/> {{ $t('move') }}</ui-button>
|
<ui-button @click="move"><fa :icon="['far', 'folder-open']"/> {{ $t('move') }}</ui-button>
|
||||||
<ui-button @click="toggleSensitive" v-if="file.isSensitive"><fa :icon="['far', 'eye']"/> {{ $t('unmark-as-sensitive') }}</ui-button>
|
<ui-button @click="toggleSensitive" v-if="file.isSensitive"><fa :icon="['far', 'eye']"/> {{ $t('unmark-as-sensitive') }}</ui-button>
|
||||||
|
@ -61,6 +61,7 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import { gcd } from '../../../../../prelude/math';
|
import { gcd } from '../../../../../prelude/math';
|
||||||
|
import { appendQuery } from '../../../../../prelude/url';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('mobile/views/components/drive.file-detail.vue'),
|
i18n: i18n('mobile/views/components/drive.file-detail.vue'),
|
||||||
|
@ -86,6 +87,10 @@ export default Vue.extend({
|
||||||
return this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? {
|
return this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? {
|
||||||
'background-color': `rgb(${ this.file.properties.avgColor.join(',') })`
|
'background-color': `rgb(${ this.file.properties.avgColor.join(',') })`
|
||||||
} : {};
|
} : {};
|
||||||
|
},
|
||||||
|
|
||||||
|
dlUrl(): string {
|
||||||
|
return appendQuery(this.file.url, 'download');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,7 @@ export function query(obj: {}): string {
|
||||||
.filter(([, v]) => Array.isArray(v) ? v.length : v !== undefined)
|
.filter(([, v]) => Array.isArray(v) ? v.length : v !== undefined)
|
||||||
.reduce((a, [k, v]) => (a[k] = v, a), {} as Record<string, any>));
|
.reduce((a, [k, v]) => (a[k] = v, a), {} as Record<string, any>));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function appendQuery(url: string, query: string): string {
|
||||||
|
return `${url}${/\?/.test(url) ? url.endsWith('?') ? '' : '&' : '?'}${query}`;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as Koa from 'koa';
|
import * as Koa from 'koa';
|
||||||
import * as send from 'koa-send';
|
import * as send from 'koa-send';
|
||||||
import * as mongodb from 'mongodb';
|
import * as mongodb from 'mongodb';
|
||||||
|
import * as rename from 'rename';
|
||||||
import DriveFile, { getDriveFileBucket } from '../../models/drive-file';
|
import DriveFile, { getDriveFileBucket } from '../../models/drive-file';
|
||||||
import DriveFileThumbnail, { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
|
import DriveFileThumbnail, { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
|
||||||
import DriveFileWebpublic, { getDriveFileWebpublicBucket } from '../../models/drive-file-webpublic';
|
import DriveFileWebpublic, { getDriveFileWebpublicBucket } from '../../models/drive-file-webpublic';
|
||||||
|
@ -62,10 +63,12 @@ export default async function(ctx: Koa.BaseContext) {
|
||||||
|
|
||||||
if (thumb != null) {
|
if (thumb != null) {
|
||||||
ctx.set('Content-Type', 'image/jpeg');
|
ctx.set('Content-Type', 'image/jpeg');
|
||||||
|
ctx.set('Content-Disposition', `filename="${rename(file.filename, { suffix: '-thumb', extname: '.jpeg' })}"`);
|
||||||
const bucket = await getDriveFileThumbnailBucket();
|
const bucket = await getDriveFileThumbnailBucket();
|
||||||
ctx.body = bucket.openDownloadStream(thumb._id);
|
ctx.body = bucket.openDownloadStream(thumb._id);
|
||||||
} else {
|
} else {
|
||||||
if (file.contentType.startsWith('image/')) {
|
if (file.contentType.startsWith('image/')) {
|
||||||
|
ctx.set('Content-Disposition', `filename="${file.filename}"`);
|
||||||
await sendRaw();
|
await sendRaw();
|
||||||
} else {
|
} else {
|
||||||
ctx.status = 404;
|
ctx.status = 404;
|
||||||
|
@ -79,15 +82,17 @@ export default async function(ctx: Koa.BaseContext) {
|
||||||
|
|
||||||
if (web != null) {
|
if (web != null) {
|
||||||
ctx.set('Content-Type', file.contentType);
|
ctx.set('Content-Type', file.contentType);
|
||||||
|
ctx.set('Content-Disposition', `filename="${rename(file.filename, { suffix: '-web' })}"`);
|
||||||
|
|
||||||
const bucket = await getDriveFileWebpublicBucket();
|
const bucket = await getDriveFileWebpublicBucket();
|
||||||
ctx.body = bucket.openDownloadStream(web._id);
|
ctx.body = bucket.openDownloadStream(web._id);
|
||||||
} else {
|
} else {
|
||||||
|
ctx.set('Content-Disposition', `filename="${file.filename}"`);
|
||||||
await sendRaw();
|
await sendRaw();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ('download' in ctx.query) {
|
if ('download' in ctx.query) {
|
||||||
ctx.set('Content-Disposition', 'attachment');
|
ctx.set('Content-Disposition', `attachment; filename="${file.filename}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await sendRaw();
|
await sendRaw();
|
||||||
|
|
Loading…
Reference in New Issue