Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tus upload #3345

Merged
merged 1 commit into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions apps/files/src/mixins.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export default {
'highlightedFile',
'publicLinkPassword',
'fileSortField',
'currentFolder',
'fileSortDirectionDesc'
]),
...mapGetters(['getToken', 'capabilities']),
...mapGetters(['getToken', 'capabilities', 'configuration']),

_sidebarOpen() {
return this.highlightedFile !== null
Expand Down Expand Up @@ -408,14 +409,27 @@ export default {
} else {
basePath = this.path || ''
relativePath = pathUtil.join(basePath, relativePath)
promise = this.uploadQueue.add(() =>
this.$client.files.putFileContents(relativePath, file, {
onProgress: progress => {
this.$_ocUpload_onProgress(progress, file)
},
overwrite: overwrite
// FIXME: this might break if relativePath is not the currentFolder
// and is a mount point that has no chunk support
if (this.browserSupportsChunked && this.currentFolder.isChunkedUploadSupported) {
promise = this.uploadQueue.add(() => {
return this.uploadChunkedFile(file, pathUtil.dirname(relativePath), {
chunkSize: this.configuration.uploadChunkSize,
emitProgress: progress => {
this.$_ocUpload_onProgress(progress, file)
}
})
})
)
} else {
promise = this.uploadQueue.add(() =>
this.$client.files.putFileContents(relativePath, file, {
onProgress: progress => {
this.$_ocUpload_onProgress(progress, file)
},
overwrite: overwrite
})
)
}
}

promise
Expand Down
3 changes: 2 additions & 1 deletion apps/files/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ function _buildFile(file) {
},
isReceivedShare: function() {
return this.permissions.indexOf('S') >= 0
}
},
isChunkedUploadSupported: !!(file.getTusSupport && file.getTusSupport())
}
}

Expand Down
9 changes: 9 additions & 0 deletions changelog/unreleased/3345
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Enhancement: Add chunked upload with tus-js-client

Whenever the backend server advertises TUS support, uploading files will
use TUS as well for uploading, which makes it possible to resume failed uploads.
It is also possible to optionally set a chunk size by setting a numeric value
for "uploadChunkSize" in bytes in config.json.

https://github.com/owncloud/phoenix/issues/67
https://github.com/owncloud/phoenix/pull/3345
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"rimraf": "^3.0.0",
"start-server-and-test": "^1.9.1",
"style-loader": "^1.0.0",
"tus-js-client": "^1.8.0",
"url-search-params-polyfill": "^8.0.0",
"vue": "^2.6.10",
"vue-clipboard2": "^0.3.1",
Expand Down
2 changes: 2 additions & 0 deletions src/phoenix.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import coreTranslations from '../l10n/translations.json'

import MediaSource from './plugins/mediaSource.js'
import PhoenixPlugin from './plugins/phoenix'
import ChunkedUpload from './plugins/upload'

// --- Drag Drop ----

Expand Down Expand Up @@ -64,6 +65,7 @@ Vue.use(VueMeta, {
// optional pluginOptions
refreshOnceOnNavigation: true
})
Vue.use(ChunkedUpload)

Vue.component('drag', Drag)
Vue.component('drop', Drop)
Expand Down
57 changes: 57 additions & 0 deletions src/plugins/upload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import tus from 'tus-js-client'

export default {
install(Vue) {
Vue.mixin({
computed: {
browserSupportsChunked() {
return tus.isSupported
}
},
methods: {
uploadChunkedFile(file, path, options) {
return new Promise((resolve, reject) => {
const headers = this.$client.helpers.buildHeaders()
delete headers['OCS-APIREQUEST']
var mtime = null
if (file.lastModifiedDate) {
mtime = file.lastModifiedDate.getTime() / 1000
}
if (file.lastModified) {
mtime = file.lastModified / 1000
}
const upload = new tus.Upload(file, {
endpoint: this.$client.files.getFileUrlV2(path),
headers: headers,
chunkSize: options.chunkSize || Infinity,
removeFingerprintOnSuccess: true,
retryDelays: [0, 3000, 5000, 10000, 20000],
metadata: {
filename: file.name,
filetype: file.type,
size: file.size,
mtime: mtime
},

onError: error => {
console.error(`Error uploading file "${file}" to "${path}"`, error)
reject(error)
},

onProgress: (bytesUploaded, bytesTotal) => {
options.emitProgress({ loaded: bytesUploaded, total: bytesTotal })
},

onSuccess: () => {
resolve(`File ${upload.file.name} was successfully uploaded`)
}
})

upload.start()
return upload
})
}
}
})
}
}
1 change: 1 addition & 0 deletions src/store/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const mutations = {
state.auth = config.auth
state.openIdConnect = config.openIdConnect
state.rootFolder = config.rootFolder === undefined ? '/' : config.rootFolder
state.uploadChunkSize = config.uploadChunkSize === undefined ? Infinity : config.uploadChunkSize
state.state = config.state === undefined ? 'working' : config.state
state.applications = config.applications === undefined ? [] : config.applications
if (config.corrupted) state.corrupted = config.corrupted
Expand Down
101 changes: 100 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1956,6 +1956,11 @@ buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=

buffer-from@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0"
integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==

buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
Expand Down Expand Up @@ -2386,6 +2391,14 @@ colors@^1.1.2, colors@^1.3.3, colors@^1.4.0:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==

combine-errors@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/combine-errors/-/combine-errors-3.0.3.tgz#f4df6740083e5703a3181110c2b10551f003da86"
integrity sha1-9N9nQAg+VwOjGBEQwrEFUfAD2oY=
dependencies:
custom-error-instance "2.1.1"
lodash.uniqby "4.5.0"

combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
Expand Down Expand Up @@ -2824,6 +2837,11 @@ cuint@^0.2.2:
resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b"
integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=

custom-error-instance@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a"
integrity sha1-PPY5FIemYppiR+sMoM4ACBt+Nho=

cyclist@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
Expand Down Expand Up @@ -3887,7 +3905,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"

extend@3.0.2, extend@~3.0.2:
extend@3.0.2, extend@^3.0.2, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
Expand Down Expand Up @@ -5400,6 +5418,11 @@ join-path@^1.1.1:
url-join "0.0.1"
valid-url "^1"

js-base64@^2.4.9:
version "2.5.2"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209"
integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ==

js-stringify@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
Expand Down Expand Up @@ -5839,11 +5862,36 @@ lodash._basefor@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz#7550b4e9218ef09fad24343b612021c79b4c20c2"
integrity sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=

lodash._baseiteratee@~4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz#34a9b5543572727c3db2e78edae3c0e9e66bd102"
integrity sha1-NKm1VDVycnw9sueO2uPA6eZr0QI=
dependencies:
lodash._stringtopath "~4.8.0"

lodash._basetostring@~4.12.0:
version "4.12.0"
resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz#9327c9dc5158866b7fa4b9d42f4638e5766dd9df"
integrity sha1-kyfJ3FFYhmt/pLnUL0Y45XZt2d8=

lodash._baseuniq@~4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
integrity sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=
dependencies:
lodash._createset "~4.0.0"
lodash._root "~3.0.0"

lodash._bindcallback@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=

lodash._createset@~4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=

lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
Expand All @@ -5854,6 +5902,18 @@ lodash._isiterateecall@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=

lodash._root@~3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=

lodash._stringtopath@~4.8.0:
version "4.8.0"
resolved "https://registry.yarnpkg.com/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz#941bcf0e64266e5fc1d66fed0a6959544c576824"
integrity sha1-lBvPDmQmbl/B1m/tCmlZVExXaCQ=
dependencies:
lodash._basetostring "~4.12.0"

lodash.clone@3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-3.0.3.tgz#84688c73d32b5a90ca25616963f189252a997043"
Expand Down Expand Up @@ -5917,11 +5977,24 @@ lodash.merge@^4.6.1, lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==

lodash.throttle@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=

lodash.union@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=

lodash.uniqby@4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz#a3a17bbf62eeb6240f491846e97c1c4e2a5e1e21"
integrity sha1-o6F7v2LutiQPSRhG6XwcTipeHiE=
dependencies:
lodash._baseiteratee "~4.7.0"
lodash._baseuniq "~4.6.0"

lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
Expand Down Expand Up @@ -7526,6 +7599,14 @@ promise@^8.0.3:
dependencies:
asap "~2.0.6"

proper-lockfile@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-2.0.1.tgz#159fb06193d32003f4b3691dd2ec1a634aa80d1d"
integrity sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0=
dependencies:
graceful-fs "^4.1.2"
retry "^0.10.0"

proxy-addr@~2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
Expand Down Expand Up @@ -8125,6 +8206,11 @@ ret@~0.1.10:
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==

retry@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=

retry@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
Expand Down Expand Up @@ -9220,6 +9306,19 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"

tus-js-client@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-1.8.0.tgz#0402357bdaa90e9dee6f6734c24473808bff272b"
integrity sha512-qPX3TywqzxocTxUZtcS8X7Aik72SVMa0jKi4hWyfvRV+s9raVzzYGaP4MoJGaF0yOgm2+b6jXaVEHogxcJ8LGw==
dependencies:
buffer-from "^0.1.1"
combine-errors "^3.0.3"
extend "^3.0.2"
js-base64 "^2.4.9"
lodash.throttle "^4.1.1"
proper-lockfile "^2.0.1"
url-parse "^1.4.3"

tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
Expand Down