Skip to content

Commit beae74b

Browse files
committed
kling upload check
1 parent 4459375 commit beae74b

2 files changed

Lines changed: 172 additions & 24 deletions

File tree

app/pages/Kling.tsx

Lines changed: 104 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import {
1212
} from "@ant-design/pro-components";
1313
import { COL_SCROLL_STYLE, PRO_FORM_PROPS, SEGMENTED_PROPS } from "@/constant";
1414
import { useAppConfig } from "@/app/store";
15-
import { Alert, Col, Divider, message, Segmented, SegmentedProps } from "antd";
15+
import { Alert, Col, Divider, App, Segmented } from "antd";
1616
import { Kling, KlingApiTypes } from "@/app/providers/kling";
1717
import { RenderSubmitter } from "../render";
18+
import { beforeUpload } from "../utils";
1819

1920
const MODE_OPTIONS = [
2021
{ label: "Std-标准模式(高性能)", value: "std" },
@@ -36,6 +37,7 @@ const TASK_TYPE_OPTIONS = [
3637
const MODEL_OPTIONS = [{ label: "kling-v1", value: "kling-v1" }];
3738

3839
const KlingPage = () => {
40+
const { message } = App.useApp();
3941
const appConfig = useAppConfig();
4042
const api = new Kling("sk-sFplfAcnWY3sFCCs02Ac93Ce9cEf4984A7EdF93e70969c18");
4143

@@ -291,30 +293,10 @@ const KlingPage = () => {
291293
updateTask: (data: any[]) => void;
292294
updateError: (error: any) => void;
293295
}) => {
296+
const [uploadType, setUploadType] = useState<"base64" | "url">("base64");
294297
const [abortController, setAbortController] = useState<AbortController | null>(null);
295298
const [submitting, setSubmitting] = useState(false);
296299

297-
const handleImageUpload = async (file: File, fieldName: string) => {
298-
const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";
299-
if (!isJpgOrPng) {
300-
message.error("只能上传 JPG/PNG 文件!");
301-
return false;
302-
}
303-
const isLt10M = file.size / 1024 / 1024 < 10;
304-
if (!isLt10M) {
305-
message.error("图片大小不能超过 10MB!");
306-
return false;
307-
}
308-
309-
const reader = new FileReader();
310-
reader.readAsDataURL(file);
311-
reader.onload = () => {
312-
const base64 = (reader.result as string).split(",")[1];
313-
props.form.setFieldsValue({ [fieldName]: base64 });
314-
};
315-
return false;
316-
};
317-
318300
return (
319301
<ProForm<KlingApiTypes["generateImage2VideoTask"]["req"]>
320302
{...PRO_FORM_PROPS}
@@ -352,19 +334,117 @@ const KlingPage = () => {
352334
<ProFormSelect name="mode" label="Mode" options={MODE_OPTIONS} />
353335
<ProFormRadio.Group name="duration" label="Duration" options={DURATION_OPTIONS} />
354336

337+
<ProFormRadio.Group
338+
label="Upload Type"
339+
options={[
340+
{ label: "Base64", value: "base64" },
341+
{ label: "URL", value: "url" },
342+
]}
343+
fieldProps={{
344+
value: uploadType,
345+
onChange: (e) => setUploadType(e.target.value),
346+
}}
347+
tooltip={"上传图片的方式,支持base64和url两种方式"}
348+
/>
349+
355350
<ProFormUploadButton
351+
name="image"
352+
label="Image"
356353
accept=".jpg,.jpeg,.png"
354+
max={1}
355+
tooltip={
356+
<>
357+
<p>支持传入图片Base64编码或图片URL(确保可访问)</p>
358+
<p>图片格式支持.jpg / .jpeg / .png</p>
359+
<p>图片文件大小不能超过10MB,图片分辨率不小于300*300px</p>
360+
</>
361+
}
362+
action={uploadType === "url" ? appConfig.getUploadConfig().action : undefined}
357363
fieldProps={{
358-
maxCount: 1,
364+
listType: "picture-card",
365+
beforeUpload: async (file) =>
366+
await beforeUpload(
367+
file,
368+
[-1, 10],
369+
[
370+
[300, 300],
371+
[-1, -1],
372+
],
373+
(msg) => message.error(msg),
374+
),
375+
...(uploadType === "url" && {
376+
headers: {
377+
Authorization: appConfig.getUploadConfig().auth,
378+
},
379+
onChange: (info) => {
380+
const getValueByPosition = (obj: any, position: readonly any[]) => {
381+
return position.reduce((acc, key) => acc && acc[key], obj);
382+
};
383+
384+
if (info.file.status === "done") {
385+
try {
386+
const response = info.file.response;
387+
if (response) {
388+
info.file.url = getValueByPosition(response, appConfig.getUploadConfig().position);
389+
}
390+
} catch (e) {
391+
console.error(e);
392+
}
393+
}
394+
},
395+
}),
359396
}}
360397
/>
361398

362399
<ProFormUploadButton
400+
name="image_tail"
401+
label="Image Tail"
363402
accept=".jpg,.jpeg,.png"
403+
max={1}
404+
tooltip={
405+
<>
406+
<p>支持传入图片Base64编码或图片URL(确保可访问)</p>
407+
<p>图片格式支持.jpg / .jpeg / .png</p>
408+
<p>图片文件大小不能超过10MB,图片分辨率不小于300*300px</p>
409+
</>
410+
}
411+
action={uploadType === "url" ? appConfig.getUploadConfig().action : undefined}
364412
fieldProps={{
365-
maxCount: 1,
413+
listType: "picture-card",
414+
beforeUpload: async (file) =>
415+
await beforeUpload(
416+
file,
417+
[-1, 10],
418+
[
419+
[300, 300],
420+
[-1, -1],
421+
],
422+
(msg) => message.error(msg),
423+
),
424+
...(uploadType === "url" && {
425+
headers: {
426+
Authorization: appConfig.getUploadConfig().auth,
427+
},
428+
onChange: (info) => {
429+
const getValueByPosition = (obj: any, position: readonly any[]) => {
430+
return position.reduce((acc, key) => acc && acc[key], obj);
431+
};
432+
433+
if (info.file.status === "done") {
434+
try {
435+
const response = info.file.response;
436+
if (response) {
437+
info.file.url = getValueByPosition(response, appConfig.getUploadConfig().position);
438+
}
439+
} catch (e) {
440+
console.error(e);
441+
}
442+
}
443+
},
444+
}),
366445
}}
367446
/>
447+
368448
<ProFormTextArea
369449
name="prompt"
370450
label="Prompt"

app/utils.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Ajv from "ajv";
2+
import { Upload } from "antd";
23

34
export function safeJsonParse(jsonString: any, defaultValue: object): object {
45
if (typeof jsonString !== "string") return defaultValue;
@@ -188,3 +189,70 @@ export function CloseAllSound(audio?: any): void {
188189
export function noApiKeys(key: string): boolean {
189190
return key === "" || key === undefined || key === null;
190191
}
192+
193+
/**
194+
* @description 检查图片是否符合上传要求
195+
* @param file 图片文件
196+
* @param fileSizeLimit 图片大小限制,单位为MB,[最小值, 最大值],-1表示不限制
197+
* @param pxLimit 图片分辨率限制,单位为px,[[最小宽度, 最小高度], [最大宽度, 最大高度]], -1表示不限制
198+
* @param onErrorMsg 错误信息回调函数
199+
* @returns Promise<Upload.LIST_IGNORE | true>
200+
*/
201+
export const beforeUpload = async (
202+
file: File,
203+
fileSizeLimit: number[],
204+
pxLimit: number[][],
205+
onErrorMsg: (msg: string) => void,
206+
): Promise<true | any> => {
207+
// 检查是否矛盾
208+
if (fileSizeLimit[0] !== -1 && fileSizeLimit[1] !== -1 && fileSizeLimit[0] > fileSizeLimit[1]) {
209+
onErrorMsg(`图片大小限制矛盾!`);
210+
return Upload.LIST_IGNORE;
211+
}
212+
if (pxLimit[0][0] !== -1 && pxLimit[1][0] !== -1 && pxLimit[0][0] > pxLimit[1][0]) {
213+
onErrorMsg(`图片分辨率(宽)限制矛盾!`);
214+
return Upload.LIST_IGNORE;
215+
}
216+
if (pxLimit[0][1] !== -1 && pxLimit[1][1] !== -1 && pxLimit[0][1] > pxLimit[1][1]) {
217+
onErrorMsg(`图片分辨率(高)限制矛盾!`);
218+
return Upload.LIST_IGNORE;
219+
}
220+
// 检查图片大小是否在限制范围内
221+
const fileSizeMb = file.size / 1024 / 1024;
222+
if (fileSizeLimit[0] !== 0 && fileSizeMb < fileSizeLimit[0]) {
223+
onErrorMsg(`图片大小不能小于 ${fileSizeLimit[0]}MB!`);
224+
return Upload.LIST_IGNORE;
225+
} else if (fileSizeMb > fileSizeLimit[1]) {
226+
onErrorMsg(`图片大小不能大于 ${fileSizeLimit[1]}MB!`);
227+
return Upload.LIST_IGNORE;
228+
}
229+
230+
const getImageSize = (file: File): Promise<number[]> => {
231+
return new Promise((resolve, reject) => {
232+
const img = new Image();
233+
img.src = URL.createObjectURL(file);
234+
img.onload = () => {
235+
const { width, height } = img;
236+
console.log("image size", width, height);
237+
URL.revokeObjectURL(img.src);
238+
resolve([width, height]);
239+
};
240+
img.onerror = () => {
241+
console.log("image error");
242+
URL.revokeObjectURL(img.src);
243+
reject(new Error("Failed to load image"));
244+
};
245+
});
246+
};
247+
248+
// 检查图片尺寸是否在限制范围内
249+
const [width, height] = await getImageSize(file);
250+
if ((pxLimit[0][0] !== -1 && width < pxLimit[0][0]) || (pxLimit[0][1] !== -1 && height < pxLimit[0][1])) {
251+
onErrorMsg(`图片分辨率不能小于 ${pxLimit[0][0]}px*${pxLimit[0][1]}px (当前: ${width}px*${height}px)`);
252+
return Upload.LIST_IGNORE;
253+
} else if ((pxLimit[1][0] !== -1 && width > pxLimit[1][0]) || (pxLimit[1][1] !== -1 && height > pxLimit[1][1])) {
254+
onErrorMsg(`图片分辨率不能大于 ${pxLimit[1][0]}px*${pxLimit[1][1]}px (当前: ${width}px*${height}px)`);
255+
return Upload.LIST_IGNORE;
256+
}
257+
return true;
258+
};

0 commit comments

Comments
 (0)