mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
added file downloads to frontend
This commit is contained in:
@ -8,13 +8,28 @@
|
||||
<div v-for="item in files" :key="item.name" class="files-list-item">
|
||||
<i :class="fileIcon(item)" />
|
||||
<p>{{ item.name }}</p>
|
||||
<p class="file-size">{{ fileSize(item.size) }}</p>
|
||||
<i v-if="item.type !== 'dir'" class="fas fa-download download"
|
||||
@click="() => download(item)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="files-transfer" @dragover.prevent @drop.prevent="onFileDrop">
|
||||
<i class="fas fa-file-arrow-up" />
|
||||
<p>Drag files here to upload</p>
|
||||
<div class="transfer-area">
|
||||
<div class="transfers" v-if="transfers.length > 0">
|
||||
<p>Downloads</p>
|
||||
<div v-for="download in downloads" :key="download.name" class="transfers-list-item">
|
||||
<div class="transfer-info">
|
||||
<p>{{ download.name }}</p>
|
||||
<p class="file-size">{{ Math.max(100, Math.round(download.progress / download.size * 100))}}%</p>
|
||||
<i class="fas fa-xmark remove-transfer" @click="() => removeTransfer(download)"></i>
|
||||
</div>
|
||||
<progress class="transfer-progress" :aria-label="download.name + ' progress'" :value="download.progress"
|
||||
:max="download.size"></progress>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-area" @dragover.prevent @drop.prevent="onFileDrop">
|
||||
<i class="fas fa-file-arrow-up" />
|
||||
<p>Drag files here to upload</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -79,30 +94,63 @@
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.refresh, .download {
|
||||
.refresh {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.refresh:hover, .download:hover {
|
||||
.file-size {
|
||||
margin-left: auto;
|
||||
margin-right: 0.5em;
|
||||
color: rgba($color: #fff, $alpha: 0.40);
|
||||
}
|
||||
|
||||
.refresh:hover, .download:hover, .remove-transfer:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.files-transfer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
margin: auto 10px 10px 10px;
|
||||
.transfer-area {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.transfers {
|
||||
margin: 10px 10px 10px 10px;
|
||||
background-color: rgba($color: #fff, $alpha: 0.05);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.files-transfer > i {
|
||||
.transfers > p {
|
||||
padding: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.transfer-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.transfer-progress {
|
||||
margin: 0px 10px 10px 10px;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
margin: 10px 10px 10px 10px;
|
||||
background-color: rgba($color: #fff, $alpha: 0.05);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.upload-area > i {
|
||||
font-size: 4em;
|
||||
margin: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
.files-transfer > p {
|
||||
.upload-area > p {
|
||||
margin: 0px 10px 10px 10px;
|
||||
}
|
||||
|
||||
@ -115,6 +163,7 @@
|
||||
|
||||
import Markdown from './markdown'
|
||||
import Content from './context.vue'
|
||||
import { FileTransfer } from '~/neko/types'
|
||||
|
||||
@Component({
|
||||
name: 'neko-files',
|
||||
@ -132,13 +181,68 @@
|
||||
get files() {
|
||||
return this.$accessor.files.files
|
||||
}
|
||||
|
||||
get transfers() {
|
||||
return this.$accessor.files.transfers
|
||||
}
|
||||
|
||||
get downloads() {
|
||||
return this.$accessor.files.transfers.filter((t => t.direction === 'download'))
|
||||
}
|
||||
|
||||
get uploads() {
|
||||
return this.$accessor.files.transfers.filter((t => t.direction === 'upload'))
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.$accessor.files.refresh()
|
||||
}
|
||||
|
||||
download(item: any) {
|
||||
console.log(item.name);
|
||||
const url = `/file?pwd=${this.$accessor.password}&filename=${item.name}`
|
||||
let transfer: FileTransfer = {
|
||||
id: Math.round(Math.random() * 10000),
|
||||
name: item.name,
|
||||
direction: 'download',
|
||||
// this is just an estimation, but for large files the content length
|
||||
// is not sent (chunked transfer)
|
||||
size: item.size,
|
||||
progress: 0,
|
||||
status: 'pending',
|
||||
axios: null,
|
||||
// TODO add support for aborting in progress requests, requires axios >=0.22
|
||||
abortController: null
|
||||
}
|
||||
transfer.axios = this.$http.get(url, {
|
||||
responseType: 'blob',
|
||||
onDownloadProgress: (x) => {
|
||||
transfer.progress = x.loaded
|
||||
|
||||
if (x.lengthComputable) {
|
||||
transfer.size = x.total
|
||||
}
|
||||
if (transfer.progress === transfer.size) {
|
||||
transfer.status = 'completed'
|
||||
}
|
||||
}
|
||||
}).then((res) => {
|
||||
const url = window.URL
|
||||
.createObjectURL(new Blob([res.data]))
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.setAttribute('download', item.name)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}).catch((err) => {
|
||||
this.$log.error(err)
|
||||
})
|
||||
this.$accessor.files.addTransfer(transfer)
|
||||
}
|
||||
|
||||
removeTransfer(item: FileTransfer) {
|
||||
console.log(item)
|
||||
this.$accessor.files.removeTransfer(item)
|
||||
}
|
||||
|
||||
fileIcon(file: any) {
|
||||
@ -169,6 +273,22 @@
|
||||
return className;
|
||||
}
|
||||
|
||||
fileSize(size: number) {
|
||||
if (size < 1000) {
|
||||
return `${size} b`
|
||||
}
|
||||
if (size < 1000 ** 2) {
|
||||
return `${(size / 1000).toFixed(2)} kb`
|
||||
}
|
||||
if (size < 1000 ** 3) {
|
||||
return `${(size / 1000 ** 2).toFixed(2)} mb`
|
||||
}
|
||||
if (size < 1000 ** 4) {
|
||||
return `${(size / 1000 ** 3).toFixed(2)} gb`
|
||||
}
|
||||
return `${(size / 1000 ** 4).toFixed(3)} tb`
|
||||
}
|
||||
|
||||
onFileDrop(e: any) {
|
||||
console.log('file dropped', e)
|
||||
console.log(e.dataTransfer.files)
|
||||
|
Reference in New Issue
Block a user