Basic file preview

This commit is contained in:
Milos Stojanovic
2020-02-20 14:03:51 +01:00
parent 37dbc2b76b
commit b8f7d000fb
6 changed files with 107 additions and 10 deletions

View File

@@ -78,6 +78,19 @@ class DownloadController
'binary'
);
// @codeCoverageIgnoreStart
if (APP_ENV == 'development') {
$streamedResponse->headers->set(
'Access-Control-Allow-Origin',
$request->headers->get('Origin')
);
$streamedResponse->headers->set(
'Access-Control-Allow-Credentials',
'true'
);
}
// @codeCoverageIgnoreEnd
// close session so we can continue streaming, note: dev is single-threaded
$this->session->save();

View File

@@ -1,4 +1,5 @@
import axios from 'axios'
import { Base64 } from 'js-base64'
const api = {
getConfig() {
@@ -190,6 +191,13 @@ const api = {
.catch(error => reject(error))
})
},
downloadItem (params) {
return new Promise((resolve, reject) => {
axios.get('download&path='+encodeURIComponent(Base64.encode(params.path)))
.then(res => resolve(res.data))
.catch(error => reject(error))
})
},
}
export default api

View File

@@ -1,6 +1,8 @@
import Vue from 'vue'
import moment from 'moment'
import store from '../store.js'
import api from '../api/api'
import { Base64 } from 'js-base64'
import english from '../translations/english'
import spanish from '../translations/spanish'
@@ -46,7 +48,7 @@ const funcs = {
let args = rest
if(!available_languages[language] || available_languages[language][term] == undefined) {
// translation required
return 'TR: '+term
return term
}
return available_languages[language][term].replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
@@ -116,7 +118,10 @@ const funcs = {
type: 'is-danger',
duration: 5000,
})
}
},
getDownloadLink(path) {
return Vue.config.baseURL+'/download&path='+encodeURIComponent(Base64.encode(path))
},
}
}

View File

@@ -70,6 +70,7 @@ const data = {
'Updated': 'Updated',
'Deleted': 'Deleted',
'Your file is ready': 'Your file is ready',
'View': 'View',
}
export default data

View File

@@ -113,6 +113,9 @@
<b-dropdown-item v-if="props.row.type == 'file' && can('download')" aria-role="listitem" @click="download(props.row)">
<b-icon icon="download" size="is-small" /> {{ lang('Download') }}
</b-dropdown-item>
<b-dropdown-item v-if="props.row.type == 'file' && can('read')" aria-role="listitem" @click="preview(props.row)">
<b-icon icon="file-alt" size="is-small" /> {{ lang('View') }}
</b-dropdown-item>
<b-dropdown-item v-if="can('write')" aria-role="listitem" @click="copy($event, props.row)">
<b-icon icon="copy" size="is-small" /> {{ lang('Copy') }}
</b-dropdown-item>
@@ -151,11 +154,11 @@
import Vue from 'vue'
import Menu from './partials/Menu'
import Tree from './partials/Tree'
import Preview from './partials/Preview'
import Pagination from './partials/Pagination'
import Upload from './partials/Upload'
import api from '../api/api'
import VueClipboard from 'vue-clipboard2'
import { Base64 } from 'js-base64'
import _ from 'lodash'
Vue.use(VueClipboard)
@@ -250,7 +253,7 @@ export default {
if (item.type == 'dir' || item.type == 'back') {
this.goTo(item.path)
} else {
this.download(item)
this.preview(item)
}
},
selectDir() {
@@ -335,17 +338,19 @@ export default {
this.handleError(error)
})
},
getDownloadLink(item) {
return Vue.config.baseURL+'/download&path='+encodeURIComponent(Base64.encode(item.path))
},
download(item) {
window.open(this.getDownloadLink(item), '_blank')
window.open(this.getDownloadLink(item.path), '_blank')
},
search() {
// TODO: create search logic
},
edit() {
// TODO: create edit file logic
preview(item) {
this.$modal.open({
parent: this,
props: { item: item },
hasModalCard: true,
component: Preview,
})
},
isArchive(item) {
return item.type == 'file' && item.name.split('.').pop() == 'zip'

View File

@@ -0,0 +1,65 @@
/* eslint-disable */
<template>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">
{{ item.name }}
</p>
</header>
<section class="modal-card-body preview">
<textarea v-if="isText()" v-model="content" class="textarea" name="content" rows="20" />
<div v-if="isImage()" class="image">
<img :src="content">
</div>
</section>
<footer class="modal-card-foot">
<button class="button" type="button" @click="$parent.close()">
{{ lang('Close') }}
</button>
</footer>
</div>
</template>
<script>
import api from '../../api/api'
export default {
name: 'Preview',
props: [ 'item' ],
data() {
return {
content: '',
}
},
mounted() {
if (this.isText()) {
api.downloadItem({
path: this.item.path,
})
.then((res) => {
this.content = res
})
.catch(error => this.handleError(error))
} else if (this.isImage()) {
this.content =this.getDownloadLink(this.item.path)
}
},
methods: {
isText() {
return this.hasExtension(['.txt', '.html', '.css', '.js', '.ts', '.php'])
},
isImage() {
return this.hasExtension(['.jpg', '.jpeg', '.gif', '.png'])
},
hasExtension(exts) {
return (new RegExp('(' + exts.join('|').replace(/\./g, '\\.') + ')$', 'i')).test(this.item.path)
},
},
}
</script>
<style scoped>
.preview {
min-height: 450px;
}
</style>