correct way for nextcloud

This commit is contained in:
fyears 2024-05-20 09:56:09 +08:00
parent 69e72eae1d
commit 7b3600a46f
2 changed files with 74 additions and 60 deletions

View File

@ -233,6 +233,7 @@ export class FakeFsWebdav extends FakeFs {
supportNativePartial: boolean; supportNativePartial: boolean;
isNextcloud: boolean; isNextcloud: boolean;
nextcloudUploadServerAddress: string;
constructor( constructor(
webdavConfig: WebdavConfig, webdavConfig: WebdavConfig,
@ -249,6 +250,7 @@ export class FakeFsWebdav extends FakeFs {
this.supportNativePartial = false; this.supportNativePartial = false;
this.isNextcloud = false; this.isNextcloud = false;
this.nextcloudUploadServerAddress = "";
} }
async _init() { async _init() {
@ -322,21 +324,50 @@ export class FakeFsWebdav extends FakeFs {
await this._checkPartialSupport(); await this._checkPartialSupport();
} }
_getnextcloudUploadServerAddress = () => {
const s = this.webdavConfig.address.split("/");
if (
s.length > 3 &&
s[s.length - 3] === "dav" &&
s[s.length - 2] === "files" &&
s[s.length - 1] !== ""
) {
s[s.length - 2] = "uploads";
return s.join("/");
}
throw Error(`cannot construct upload address for ${s}`);
};
async _checkPartialSupport() { async _checkPartialSupport() {
const compliance = await this.client.getDAVCompliance( const compliance = await this.client.getDAVCompliance(
`/${this.remoteBaseDir}/` `/${this.remoteBaseDir}/`
); );
for (const c of compliance.compliance) { for (const c of compliance.compliance) {
// nextcloud AND with an account
if ( if (
c.toLocaleLowerCase().includes("nextcloud") && c.toLocaleLowerCase().includes("nextcloud") &&
this.webdavConfig.username !== "" && this.webdavConfig.username !== "" &&
this.webdavConfig.password !== "" this.webdavConfig.password !== ""
) { ) {
// nextcloud AND with an account // the address is parsable
this.isNextcloud = true; const s = this.webdavConfig.address.split("/");
console.debug(`isNextcloud=true`); if (
return true; s.length > 3 &&
s[s.length - 3] === "dav" &&
s[s.length - 2] === "files" &&
s[s.length - 1] !== ""
) {
this.isNextcloud = true;
this.nextcloudUploadServerAddress =
this._getnextcloudUploadServerAddress();
console.debug(
`isNextcloud=${this.isNextcloud}, uploadFolder=${this.nextcloudUploadServerAddress}`
);
return true;
} else {
return false;
}
} }
} }
@ -530,16 +561,16 @@ export class FakeFsWebdav extends FakeFs {
`we fail to write file partially, so downgrade to full and ignore the error:` `we fail to write file partially, so downgrade to full and ignore the error:`
); );
console.error(e); console.error(e);
// throw e; throw e;
this.isNextcloud = false; // this.isNextcloud = false;
this.supportNativePartial = false; // this.supportNativePartial = false;
return await this._writeFileFromRootFull( // return await this._writeFileFromRootFull(
key, // key,
content, // content,
mtime, // mtime,
ctime, // ctime,
origKey // origKey
); // );
} }
} }
@ -586,40 +617,38 @@ export class FakeFsWebdav extends FakeFs {
console.debug(`destUrl=${destUrl}`); console.debug(`destUrl=${destUrl}`);
const getTmpFolder = (x: string) => { const getTmpFolder = (x: string) => {
if (x.endsWith("/")) {
throw Error(`file to upload by chunk should not ends with /`);
}
const y = x.split("/"); const y = x.split("/");
y[y.length - 1] = `${y[y.length - 1]}-${nanoid()}`; const z = encodeURI(`${y[y.length - 1]}`);
const nodot = y.join("/"); return z;
y[y.length - 1] = `.${y[y.length - 1]}`;
const withdot = y.join("/");
return {
withdot: withdot,
nodot: nodot,
};
}; };
const tmpFolders = getTmpFolder(key);
const tmpFolder = tmpFolders.withdot; const uploadServerAddress = this.nextcloudUploadServerAddress;
const tmpFolderNoDot = tmpFolders.nodot; console.debug(`uploadServerAddress=${uploadServerAddress}`);
console.debug(`tmpFolder=${tmpFolder}`); const tmpFolderName = getTmpFolder(key);
const tmpFolderUrl = `${this.webdavConfig.address}/${encodeURI(tmpFolder)}`; console.debug(`tmpFolderName=${tmpFolderName}`);
console.debug(`tmpFolderUrl=${tmpFolderUrl}`);
const clientForUpload = createClient(uploadServerAddress, {
username: this.webdavConfig.username,
password: this.webdavConfig.password,
headers: {
"Cache-Control": "no-cache",
},
authType:
this.webdavConfig.authType === "digest"
? AuthType.Digest
: AuthType.Password,
});
// create folder // create folder
await this.client.createDirectory(tmpFolder, { await clientForUpload.createDirectory(tmpFolderName, {
method: "MKCOL",
headers: { headers: {
Destination: destUrl, Destination: destUrl,
}, },
}); });
try {
const tmpFolderResult = await this.client.stat(tmpFolder);
} catch (e) {
// not exists??
try {
// try to clean no dot folder
await this.client.deleteFile(tmpFolderNoDot);
} catch (e2) {}
this.isNextcloud = false;
throw Error(`cannot create hidden file into nextcloud: ${tmpFolder}`);
}
console.debug(`finish creating folder`); console.debug(`finish creating folder`);
// upload by chunks // upload by chunks
@ -631,13 +660,13 @@ export class FakeFsWebdav extends FakeFs {
for (let i = 0; i < chunkRanges.length; ++i) { for (let i = 0; i < chunkRanges.length; ++i) {
const { start, end } = chunkRanges[i]; const { start, end } = chunkRanges[i];
const tmpFileName = `${i + 1}`.padStart(5, "0"); const tmpFileName = `${i + 1}`.padStart(5, "0");
const tmpFileNameWithFolder = `${tmpFolder}/${tmpFileName}`; const tmpFileNameWithFolder = `${tmpFolderName}/${tmpFileName}`;
console.debug( console.debug(
`start to upload chunk ${ `start to upload chunk ${
i + 1 i + 1
} to ${tmpFileNameWithFolder} with startInclusive=${start}, endInclusive=${end}` } to ${tmpFileNameWithFolder} with startInclusive=${start}, endInclusive=${end}`
); );
await this.client.putFileContents( await clientForUpload.putFileContents(
tmpFileNameWithFolder, tmpFileNameWithFolder,
content.slice(start, end + 1), content.slice(start, end + 1),
{ {
@ -651,9 +680,9 @@ export class FakeFsWebdav extends FakeFs {
console.debug(`finish upload all chunks`); console.debug(`finish upload all chunks`);
// move to assemble // move to assemble
const fakeFileToMoveUrl = `${tmpFolderUrl}/.file`; const fakeFileToMoveUrl = `${tmpFolderName}/.file`;
console.debug(`fakeFileToMoveUrl=${fakeFileToMoveUrl}`); console.debug(`fakeFileToMoveUrl=${fakeFileToMoveUrl}`);
await this.client.customRequest(fakeFileToMoveUrl, { await clientForUpload.customRequest(fakeFileToMoveUrl, {
method: "MOVE", method: "MOVE",
headers: { headers: {
Destination: destUrl, Destination: destUrl,
@ -663,21 +692,6 @@ export class FakeFsWebdav extends FakeFs {
console.debug(`finish moving file`); console.debug(`finish moving file`);
// TODO: setting X-OC-Mtime // TODO: setting X-OC-Mtime
// wait for anything broken??
await delay(1000);
// clean up!
console.debug(`try to clean up`);
try {
await this.client.deleteFile(tmpFolder);
console.debug(`finish clean up`);
} catch (e) {
console.error(
`while cleaning chunks of nextcloud, some errors occur but we ignore them:`
);
console.error(e);
}
// stat // stat
console.debug(`before stat origKey=${origKey}`); console.debug(`before stat origKey=${origKey}`);
const k = await this.stat(origKey); const k = await this.stat(origKey);

View File

@ -686,7 +686,7 @@ export const splitFileSizeToChunkRanges = (
) => { ) => {
if (totalSize < 0) { if (totalSize < 0) {
throw Error(`totalSize should not be negative`); throw Error(`totalSize should not be negative`);
} }
if (chunkSize <= 0) { if (chunkSize <= 0) {
throw Error(`chunkSize should not be negative or zero`); throw Error(`chunkSize should not be negative or zero`);
} }