Skip to content

Commit

Permalink
fix: auto replace storage prefix (#670)
Browse files Browse the repository at this point in the history
  • Loading branch information
tea-artist committed Jun 20, 2024
1 parent b139d77 commit 0735c1c
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 26 deletions.
19 changes: 12 additions & 7 deletions apps/nestjs-backend/src/features/attachments/plugins/minio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getRandomString } from '@teable/core';
import * as minio from 'minio';
import sharp from 'sharp';
import { IStorageConfig, StorageConfig } from '../../../configs/storage';
import { replaceStorageUrl } from '../../../utils/full-storage-url';
import { second } from '../../../utils/second';
import type StorageAdapter from './adapter';
import type { IPresignParams, IPresignRes, IRespHeaders } from './types';
Expand Down Expand Up @@ -40,12 +41,14 @@ export class MinioStorage implements StorageAdapter {
'Content-Length': contentLength,
};
try {
const url = await this.minioClient.presignedUrl(
uploadMethod,
bucket,
path,
expiresIn ?? second(tokenExpireIn),
requestHeaders
const url = replaceStorageUrl(
await this.minioClient.presignedUrl(
uploadMethod,
bucket,
path,
expiresIn ?? second(tokenExpireIn),
requestHeaders
)
);
return {
url,
Expand Down Expand Up @@ -93,7 +96,9 @@ export class MinioStorage implements StorageAdapter {
expiresIn: number = second(this.config.urlExpireIn),
respHeaders?: IRespHeaders
) {
return this.minioClient.presignedGetObject(bucket, path, expiresIn, respHeaders);
return replaceStorageUrl(
await this.minioClient.presignedGetObject(bucket, path, expiresIn, respHeaders)
);
}

async uploadFileWidthPath(
Expand Down
10 changes: 8 additions & 2 deletions apps/nestjs-backend/src/utils/full-storage-url.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { URL } from 'url';
import path from 'path';
import { replaceSuffix } from '@teable/core';
import { baseConfig } from '../configs/base.config';

export const getFullStorageUrl = (url: string) => {
const storagePrefix = baseConfig().storagePrefix;
return new URL(url, storagePrefix).href;
return path.join(storagePrefix, url);
};

export const replaceStorageUrl = (originalUrl: string) => {
const storagePrefix = baseConfig().storagePrefix;
return replaceSuffix(originalUrl, storagePrefix);
};
2 changes: 0 additions & 2 deletions apps/nextjs-app/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ SOCKET_PORT=3001

PUBLIC_ORIGIN=http://127.0.0.1:3000

# static assets url prefix
ASSET_PREFIX=http://127.0.0.1:3000
# storage service url prefix
STORAGE_PREFIX=http://127.0.0.1:3000

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
Textarea,
cn,
} from '@teable/ui-lib/shadcn';
import Image from 'next/image';
import { useTranslation } from 'next-i18next';
import { useEffect, useRef, useState } from 'react';
import { FieldOperator } from '@/features/app/components/field-setting';
Expand Down Expand Up @@ -140,10 +141,14 @@ export const FormEditorMain = (props: { fields: IFieldInstance[] }) => {
)}
>
{coverUrl && (
<img
<Image
src={getPreviewUrl(coverUrl)}
alt="form cover"
className="size-full object-cover"
alt="card cover"
fill
sizes="100%"
style={{
objectFit: 'cover',
}}
/>
)}
<Button
Expand All @@ -165,10 +170,12 @@ export const FormEditorMain = (props: { fields: IFieldInstance[] }) => {
<div className="group absolute left-1/2 top-[104px] ml-[-40px] size-20">
{logoUrl ? (
<>
<img
<Image
className="rounded-lg object-cover shadow-sm"
src={getPreviewUrl(logoUrl)}
alt="form logo"
className="size-full rounded-lg object-cover shadow-sm"
alt="card cover"
fill
sizes="100%"
/>
<Button
variant={'ghost'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useFields, useTableId, useView } from '@teable/sdk/hooks';
import { type FormView } from '@teable/sdk/model';
import { Button, cn, useToast } from '@teable/ui-lib/shadcn';
import { omit } from 'lodash';
import Image from 'next/image';
import { useTranslation } from 'next-i18next';
import { useMemo, useRef, useState } from 'react';
import { useLocalStorage, useMap, useSet } from 'react-use';
Expand Down Expand Up @@ -144,20 +145,26 @@ export const FormPreviewer = (props: IFormPreviewerProps) => {
)}
>
{coverUrl && (
<img
<Image
src={getPreviewUrl(coverUrl)}
alt="form cover"
className="size-full object-cover"
alt="card cover"
fill
sizes="100%"
style={{
objectFit: 'cover',
}}
/>
)}
</div>

{logoUrl && (
<div className="group absolute left-1/2 top-[104px] ml-[-40px] size-20">
<img
<Image
className="rounded-lg object-cover shadow-sm"
src={getPreviewUrl(logoUrl)}
alt="form logo"
className="size-full rounded-lg object-cover shadow-sm"
alt="card cover"
fill
sizes="100%"
/>
</div>
)}
Expand Down
15 changes: 12 additions & 3 deletions apps/nextjs-app/src/features/app/hooks/usePreviewUrl.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { useCallback } from 'react';
import { useEnv } from './useEnv';

function pathJoin(...parts: string[]) {
const separator = '/';
const replace = new RegExp(separator + '+', 'g');
return parts.join(separator).replace(replace, separator);
}

export const usePreviewUrl = () => {
const { storagePrefix } = useEnv();

return useCallback(
(urlOrPath: string) => {
const url = new URL(urlOrPath, storagePrefix);
return url.href;
(path: string) => {
if (!storagePrefix) {
console.error('storagePrefix is not set');
return path;
}
return pathJoin(storagePrefix, path);
},
[storagePrefix]
);
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './date';
export * from './dsn-parser';
export * from './clipboard';
export * from './minidenticon';
export * from './replace-suffix';
11 changes: 11 additions & 0 deletions packages/core/src/utils/replace-suffix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const replaceSuffix = (originalUrl: string, storagePrefix: string) => {
const original = new URL(originalUrl);
const suffix = new URL(storagePrefix);

const suffixPath = suffix.pathname.endsWith('/') ? suffix.pathname : suffix.pathname + '/';
const originalPath = original.pathname.startsWith('/')
? original.pathname.slice(1)
: original.pathname;

return `${suffix.origin}${suffixPath}${originalPath}${original.search}${original.hash}`;
};

0 comments on commit 0735c1c

Please sign in to comment.