Browse Source

Merge pull request #9328 from nocodb/nc-attachment-issue

fix: handle attachment issues for windows
pull/9353/head
Anbarasu 3 months ago committed by GitHub
parent
commit
2911a610e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      packages/nocodb/src/db/BaseModelSqlv2.ts
  2. 15
      packages/nocodb/src/models/PresignedUrl.ts
  3. 6
      packages/nocodb/src/modules/jobs/jobs/thumbnail-generator/thumbnail-generator.processor.ts
  4. 6
      packages/nocodb/src/plugins/mino/Minio.ts
  5. 9
      packages/nocodb/src/plugins/storage/Local.ts

4
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -8184,7 +8184,7 @@ class BaseModelSqlv2 {
}; };
const thumbnailPath = `thumbnails/${lookedUpAttachment.path.replace( const thumbnailPath = `thumbnails/${lookedUpAttachment.path.replace(
/^download\//, /^download[/\\]/i,
'', '',
)}`; )}`;
@ -8257,7 +8257,7 @@ class BaseModelSqlv2 {
} }
const thumbnailPath = `thumbnails/${attachment.path.replace( const thumbnailPath = `thumbnails/${attachment.path.replace(
/^download\//, /^download[/\\]/i,
'', '',
)}`; )}`;

15
packages/nocodb/src/models/PresignedUrl.ts

@ -1,5 +1,6 @@
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import contentDisposition from 'content-disposition'; import contentDisposition from 'content-disposition';
import slash from 'slash';
import NcPluginMgrv2 from '~/helpers/NcPluginMgrv2'; import NcPluginMgrv2 from '~/helpers/NcPluginMgrv2';
import Noco from '~/Noco'; import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache'; import NocoCache from '~/cache/NocoCache';
@ -39,7 +40,7 @@ export default class PresignedUrl {
expiresInSeconds = DEFAULT_EXPIRE_SECONDS, expiresInSeconds = DEFAULT_EXPIRE_SECONDS,
} = param; } = param;
await NocoCache.setExpiring( await NocoCache.setExpiring(
`${CacheScope.PRESIGNED_URL}:path:${path}`, `${CacheScope.PRESIGNED_URL}:path:${slash(path)}`,
{ {
path, path,
url, url,
@ -48,7 +49,7 @@ export default class PresignedUrl {
expiresInSeconds, expiresInSeconds,
); );
await NocoCache.setExpiring( await NocoCache.setExpiring(
`${CacheScope.PRESIGNED_URL}:url:${decodeURIComponent(url)}`, `${CacheScope.PRESIGNED_URL}:url:${slash(decodeURIComponent(url))}`,
{ {
path, path,
url, url,
@ -60,15 +61,15 @@ export default class PresignedUrl {
private static async delete(param: { path: string; url: string }) { private static async delete(param: { path: string; url: string }) {
const { path, url } = param; const { path, url } = param;
await NocoCache.del(`${CacheScope.PRESIGNED_URL}:path:${path}`); await NocoCache.del(`${CacheScope.PRESIGNED_URL}:path:${slash(path)}`);
await NocoCache.del(`${CacheScope.PRESIGNED_URL}:url:${url}`); await NocoCache.del(`${CacheScope.PRESIGNED_URL}:url:${slash(url)}`);
} }
public static async getPath(url: string, _ncMeta = Noco.ncMeta) { public static async getPath(url: string, _ncMeta = Noco.ncMeta) {
const urlData = const urlData =
url && url &&
(await NocoCache.get( (await NocoCache.get(
`${CacheScope.PRESIGNED_URL}:url:${url}`, `${CacheScope.PRESIGNED_URL}:url:${slash(url)}`,
CacheGetType.TYPE_OBJECT, CacheGetType.TYPE_OBJECT,
)); ));
if (!urlData) { if (!urlData) {
@ -159,7 +160,7 @@ export default class PresignedUrl {
).toString()}`; ).toString()}`;
const url = await NocoCache.get( const url = await NocoCache.get(
`${CacheScope.PRESIGNED_URL}:path:${cachePath}`, `${CacheScope.PRESIGNED_URL}:path:${slash(cachePath)}`,
CacheGetType.TYPE_OBJECT, CacheGetType.TYPE_OBJECT,
); );
@ -246,7 +247,7 @@ export default class PresignedUrl {
if (attachment?.path) { if (attachment?.path) {
nestedObj.signedPath = await PresignedUrl.getSignedUrl( nestedObj.signedPath = await PresignedUrl.getSignedUrl(
{ {
pathOrUrl: attachment.path.replace(/^download\//, ''), pathOrUrl: attachment.path.replace(/^download[/\\]/i, ''),
preview, preview,
mimetype: mimetype || attachment.mimetype, mimetype: mimetype || attachment.mimetype,
...(extra ? { ...extra } : {}), ...(extra ? { ...extra } : {}),

6
packages/nocodb/src/modules/jobs/jobs/thumbnail-generator/thumbnail-generator.processor.ts

@ -75,7 +75,7 @@ export class ThumbnailGeneratorProcessor {
tiny: path.join('nc', 'thumbnails', relativePath, 'tiny.jpg'), tiny: path.join('nc', 'thumbnails', relativePath, 'tiny.jpg'),
}; };
const sharpImage = await sharp(file, { const sharpImage = sharp(file, {
limitInputPixels: false, limitInputPixels: false,
}); });
@ -135,7 +135,7 @@ export class ThumbnailGeneratorProcessor {
relativePath = path.join( relativePath = path.join(
'nc', 'nc',
'uploads', 'uploads',
attachment.path.replace(/^download\//, ''), attachment.path.replace(/^download[/\\]/i, ''),
); );
} else if (attachment.url) { } else if (attachment.url) {
relativePath = getPathFromUrl(attachment.url).replace(/^\/+/, ''); relativePath = getPathFromUrl(attachment.url).replace(/^\/+/, '');
@ -144,7 +144,7 @@ export class ThumbnailGeneratorProcessor {
const file = await storageAdapter.fileRead(relativePath); const file = await storageAdapter.fileRead(relativePath);
// remove everything before 'nc/uploads/' (including nc/uploads/) in relativePath // remove everything before 'nc/uploads/' (including nc/uploads/) in relativePath
relativePath = relativePath.replace(/.*?nc\/uploads\//, ''); relativePath = relativePath.replace(/^.*?nc[/\\]uploads[/\\]/, '');
return { file, relativePath }; return { file, relativePath };
} }

6
packages/nocodb/src/plugins/mino/Minio.ts

@ -198,8 +198,10 @@ export default class Minio implements IStorageAdapterV2 {
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
public async fileDelete(_path: string): Promise<any> { public async fileDelete(path: string): Promise<any> {
throw new Error('Method not implemented.'); return this.minioClient.removeObject(this.input.bucket, path).then(() => {
return true;
});
} }
public async scanFiles(_globPattern: string): Promise<Readable> { public async scanFiles(_globPattern: string): Promise<Readable> {

9
packages/nocodb/src/plugins/storage/Local.ts

@ -112,15 +112,18 @@ export default class Local implements IStorageAdapterV2 {
} }
public async scanFiles(globPattern: string) { public async scanFiles(globPattern: string) {
// Normalize the path separator
globPattern = globPattern.replace(/\//g, path.sep);
// remove all dots from the glob pattern // remove all dots from the glob pattern
globPattern = globPattern.replace(/\./g, ''); globPattern = globPattern.replace(/\./g, '');
// remove the leading slash // remove the leading slash
globPattern = globPattern.replace(/^\//, ''); globPattern = globPattern.replace(/^\//, '');
// make sure pattern starts with nc/uploads/ // Ensure the pattern starts with 'nc/uploads/'
if (!globPattern.startsWith('nc/uploads/')) { if (!globPattern.startsWith(path.join('nc', 'uploads'))) {
globPattern = `nc/uploads/${globPattern}`; globPattern = path.join('nc', 'uploads', globPattern);
} }
const stream = globStream(globPattern, { const stream = globStream(globPattern, {

Loading…
Cancel
Save