mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
All: Handle case where file is left half-uploaded on Nextcloud instance (possibly an ocloud.de issue only)
This commit is contained in:
parent
2805ae2acf
commit
7b760d03ef
@ -161,6 +161,8 @@ class WebDavApi {
|
||||
|
||||
let response = null;
|
||||
|
||||
// console.info('WebDAV', method + ' ' + path, headers, options);
|
||||
|
||||
if (options.source == 'file' && (method == 'POST' || method == 'PUT')) {
|
||||
response = await shim.uploadBlob(url, fetchOptions);
|
||||
} else if (options.target == 'string') {
|
||||
|
@ -4,6 +4,8 @@ const { basicDelta } = require('lib/file-api');
|
||||
const { rtrimSlashes, ltrimSlashes } = require('lib/path-utils.js');
|
||||
const Entities = require('html-entities').AllHtmlEntities;
|
||||
const html_entity_decode = (new Entities()).decode;
|
||||
const { shim } = require('lib/shim');
|
||||
const { basename } = require('lib/path-utils');
|
||||
|
||||
class FileApiDriverWebDav {
|
||||
|
||||
@ -20,6 +22,7 @@ class FileApiDriverWebDav {
|
||||
const result = await this.api().execPropFind(path, 0, [
|
||||
'd:getlastmodified',
|
||||
'd:resourcetype',
|
||||
'd:getcontentlength', // Remove this once PUT call issue is sorted out
|
||||
]);
|
||||
|
||||
const resource = this.api().objectFromJson(result, ['d:multistatus', 'd:response', 0]);
|
||||
@ -34,6 +37,9 @@ class FileApiDriverWebDav {
|
||||
const isCollection = this.api().stringFromJson(resource, ['d:propstat', 0, 'd:prop', 0, 'd:resourcetype', 0, 'd:collection', 0]);
|
||||
const lastModifiedString = this.api().stringFromJson(resource, ['d:propstat', 0, 'd:prop', 0, 'd:getlastmodified', 0]);
|
||||
|
||||
const sizeDONOTUSE = Number(this.api().stringFromJson(resource, ['d:propstat', 0, 'd:prop', 0, 'd:getcontentlength', 0]));
|
||||
if (isNaN(sizeDONOTUSE)) throw new Error('Cannot get content size: ' + JSON.stringify(resource));
|
||||
|
||||
if (!lastModifiedString) throw new Error('Could not get lastModified date: ' + JSON.stringify(resource));
|
||||
|
||||
const lastModifiedDate = new Date(lastModifiedString);
|
||||
@ -44,6 +50,7 @@ class FileApiDriverWebDav {
|
||||
created_time: lastModifiedDate.getTime(),
|
||||
updated_time: lastModifiedDate.getTime(),
|
||||
isDir: isCollection === '',
|
||||
sizeDONOTUSE: sizeDONOTUSE, // This property is used only for the WebDAV PUT hack (see below) so mark it as such so that it can be removed with the hack later on.
|
||||
};
|
||||
}
|
||||
|
||||
@ -229,7 +236,32 @@ class FileApiDriverWebDav {
|
||||
}
|
||||
|
||||
async put(path, content, options = null) {
|
||||
await this.api().exec('PUT', path, content, null, options);
|
||||
// In theory, if a client doesn't complete an upload, the file will not appear in the Nextcloud app. Likewise if
|
||||
// the server interrupts the upload midway, the client should receive some kind of error and try uploading the
|
||||
// file again next time. At the very least the file should not appear half-uploaded on the server. In practice
|
||||
// however it seems some files might end up half uploaded on the server (at least on ocloud.de) so, for now,
|
||||
// instead of doing a simple PUT, we do it to a temp file on Nextcloud, then check the file size and, if it
|
||||
// matches, move it its actual place (hoping the server won't mess up and only copy half of the file).
|
||||
// This is innefficient so once the bug is better understood it should hopefully be possible to go back to
|
||||
// using a single PUT call.
|
||||
|
||||
let contentSize = 0;
|
||||
if (content) contentSize = content.length;
|
||||
if (options && options.path) {
|
||||
const stat = await shim.fsDriver().stat(options.path);
|
||||
contentSize = stat.size;
|
||||
}
|
||||
|
||||
const tempPath = this.fileApi_.tempDirName() + '/' + basename(path) + '_' + Date.now();
|
||||
await this.api().exec('PUT', tempPath, content, null, options);
|
||||
|
||||
const stat = await this.stat(tempPath);
|
||||
if (stat.sizeDONOTUSE != contentSize) {
|
||||
// await this.delete(tempPath);
|
||||
throw new Error('WebDAV PUT - Size check failed for ' + tempPath + ' Expected: ' + contentSize + '. Found: ' + stat.sizeDONOTUSE);
|
||||
}
|
||||
|
||||
await this.move(tempPath, path);
|
||||
}
|
||||
|
||||
async delete(path) {
|
||||
@ -241,7 +273,9 @@ class FileApiDriverWebDav {
|
||||
}
|
||||
|
||||
async move(oldPath, newPath) {
|
||||
throw new Error('Not implemented');
|
||||
await this.api().exec('MOVE', oldPath, null, {
|
||||
'Destination': this.api().baseUrl() + '/' + newPath,
|
||||
});
|
||||
}
|
||||
|
||||
format() {
|
||||
|
@ -12,6 +12,17 @@ class FileApi {
|
||||
this.driver_ = driver;
|
||||
this.logger_ = new Logger();
|
||||
this.syncTargetId_ = null;
|
||||
this.tempDirName_ = null;
|
||||
this.driver_.fileApi_ = this;
|
||||
}
|
||||
|
||||
tempDirName() {
|
||||
if (this.tempDirName_ === null) throw Error('Temp dir not set!');
|
||||
return this.tempDirName_;
|
||||
}
|
||||
|
||||
setTempDirName(v) {
|
||||
this.tempDirName_ = v;
|
||||
}
|
||||
|
||||
fsDriver() {
|
||||
@ -40,9 +51,10 @@ class FileApi {
|
||||
}
|
||||
|
||||
fullPath_(path) {
|
||||
let output = this.baseDir_;
|
||||
if (path != '') output += '/' + path;
|
||||
return output;
|
||||
let output = [];
|
||||
if (this.baseDir_) output.push(this.baseDir_);
|
||||
if (path) output.push(path);
|
||||
return output.join('/');
|
||||
}
|
||||
|
||||
// DRIVER MUST RETURN PATHS RELATIVE TO `path`
|
||||
|
@ -18,7 +18,7 @@ class Synchronizer {
|
||||
this.state_ = 'idle';
|
||||
this.db_ = db;
|
||||
this.api_ = api;
|
||||
//this.syncDirName_ = '.sync';
|
||||
this.syncDirName_ = '.sync';
|
||||
this.resourceDirName_ = '.resource';
|
||||
this.logger_ = new Logger();
|
||||
this.appType_ = appType;
|
||||
@ -195,7 +195,8 @@ class Synchronizer {
|
||||
this.logSyncOperation('starting', null, null, 'Starting synchronisation to target ' + syncTargetId + '... [' + synchronizationId + ']');
|
||||
|
||||
try {
|
||||
//await this.api().mkdir(this.syncDirName_);
|
||||
await this.api().mkdir(this.syncDirName_);
|
||||
this.api().setTempDirName(this.syncDirName_);
|
||||
await this.api().mkdir(this.resourceDirName_);
|
||||
|
||||
let donePaths = [];
|
||||
|
Loading…
Reference in New Issue
Block a user