refactor: 将前后端通信由app端移至server端 #74
@ -122,6 +122,8 @@
|
|||||||
const errorText = computed(() => error.value?.message ?? null);
|
const errorText = computed(() => error.value?.message ?? null);
|
||||||
const fileMeta = computed(() => props.file ?? data.value ?? null);
|
const fileMeta = computed(() => props.file ?? data.value ?? null);
|
||||||
|
|
||||||
|
logger.debug('FilePreviewer - fileMeta:', fileMeta.value);
|
||||||
|
|
||||||
/** 预览源地址:支持在 file.url 上追加额外 query(如临时 token、inline) */
|
/** 预览源地址:支持在 file.url 上追加额外 query(如临时 token、inline) */
|
||||||
const src = computed<string>(() => {
|
const src = computed<string>(() => {
|
||||||
if (!fileMeta.value) return '';
|
if (!fileMeta.value) return '';
|
||||||
|
|||||||
@ -1,19 +1,14 @@
|
|||||||
export const useDirectusFiles = () => {
|
export const useDirectusFiles = () => {
|
||||||
const config = useRuntimeConfig();
|
|
||||||
const baseUrl = config.public.directus.url;
|
|
||||||
|
|
||||||
const getFileUrl = (
|
const getFileUrl = (
|
||||||
id?: string | null,
|
id?: string | null,
|
||||||
options?: Record<string, string | number | boolean>
|
options?: Record<string, string | number | boolean>
|
||||||
): string => {
|
): string => {
|
||||||
if (!id) return '';
|
if (!id) return '';
|
||||||
const query = options
|
|
||||||
? '?' +
|
const params = new URLSearchParams(
|
||||||
new URLSearchParams(
|
options as Record<string, string>
|
||||||
Object.entries(options).map(([key, value]) => [key, String(value)])
|
).toString();
|
||||||
).toString()
|
return `/api/assets/${id}${params ? `?${params}` : ''}`;
|
||||||
: '';
|
|
||||||
return `${baseUrl}/assets/${id}${query}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,8 +1,4 @@
|
|||||||
export const useDirectusImage = () => {
|
export const useDirectusImage = () => {
|
||||||
const config = useRuntimeConfig();
|
|
||||||
const baseUrl = config.public.directus.url;
|
|
||||||
const token = config.public.directus.token;
|
|
||||||
|
|
||||||
type DirectusAssetParams = {
|
type DirectusAssetParams = {
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
@ -13,19 +9,11 @@ export const useDirectusImage = () => {
|
|||||||
|
|
||||||
const getImageUrl = (id?: string | null, options?: DirectusAssetParams) => {
|
const getImageUrl = (id?: string | null, options?: DirectusAssetParams) => {
|
||||||
if (!id) return '';
|
if (!id) return '';
|
||||||
const queryToken = token ? 'access_token=' + token : '';
|
|
||||||
const queryOptions = options
|
const params = new URLSearchParams(
|
||||||
? new URLSearchParams(
|
options as Record<string, string>
|
||||||
Object.fromEntries(
|
).toString();
|
||||||
Object.entries(options).map(([key, value]) => [key, String(value)])
|
return `/api/assets/${id}${params ? `?${params}` : ''}`;
|
||||||
)
|
|
||||||
).toString
|
|
||||||
: '';
|
|
||||||
const query =
|
|
||||||
queryToken || queryOptions
|
|
||||||
? `?${[queryToken, queryOptions].filter(Boolean).join('&')}`
|
|
||||||
: '';
|
|
||||||
return `${baseUrl}/assets/${id}${query}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return { getImageUrl };
|
return { getImageUrl };
|
||||||
|
|||||||
36
server/api/assets/[id].ts
Normal file
36
server/api/assets/[id].ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const id = getRouterParam(event, 'id');
|
||||||
|
if (!id)
|
||||||
|
throw createError({
|
||||||
|
statusCode: 400,
|
||||||
|
statusMessage: 'ID parameter is required',
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = new URL(`${useRuntimeConfig().public.directus.url}/assets/${id}`);
|
||||||
|
|
||||||
|
const query = getQuery(event);
|
||||||
|
Object.entries(query).forEach(([key, value]) => {
|
||||||
|
url.searchParams.set(key, String(value));
|
||||||
|
});
|
||||||
|
|
||||||
|
const token = useRuntimeConfig().public.directus.token || '';
|
||||||
|
const res = await fetch(url.toString(), {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: res.status,
|
||||||
|
statusMessage: `Failed to fetch asset: ${res.statusText}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType =
|
||||||
|
res.headers.get('Content-Type') || 'application/octet-stream';
|
||||||
|
setHeader(event, 'Content-Type', contentType);
|
||||||
|
setHeader(event, 'Cache-Control', 'public, max-age=86400, immutable');
|
||||||
|
|
||||||
|
return res.body;
|
||||||
|
});
|
||||||
@ -41,7 +41,7 @@ export async function getFileMeta(id: string): Promise<FileMeta | null> {
|
|||||||
width: file.width ?? undefined,
|
width: file.width ?? undefined,
|
||||||
height: file.height ?? undefined,
|
height: file.height ?? undefined,
|
||||||
uploaded_on: file.uploaded_on ?? undefined,
|
uploaded_on: file.uploaded_on ?? undefined,
|
||||||
url: `${baseUrl}/assets/${file.id}`,
|
url: `/api/assets/${file.id}`,
|
||||||
previewable: isPreviewable(file.type),
|
previewable: isPreviewable(file.type),
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user