feat: support base64 image in frontend

This commit is contained in:
Zhang Minghan 2024-02-15 13:18:58 +08:00
parent 6e54c6444f
commit 4cd5c422c0
2 changed files with 18 additions and 5 deletions

View File

@ -1,5 +1,5 @@
import { Download, Eye, File } from "lucide-react"; import { Download, Eye, File } from "lucide-react";
import { saveAsFile, saveBlobAsFile } from "@/utils/dom.ts"; import { saveAsFile, saveBlobAsFile, saveImageAsFile } from "@/utils/dom.ts";
import { useMemo } from "react"; import { useMemo } from "react";
import { Button } from "@/components/ui/button.tsx"; import { Button } from "@/components/ui/button.tsx";
import FileViewer from "@/components/FileViewer.tsx"; import FileViewer from "@/components/FileViewer.tsx";
@ -15,11 +15,16 @@ import FileViewer from "@/components/FileViewer.tsx";
export function parseFile(data: string, acceptDownload?: boolean) { export function parseFile(data: string, acceptDownload?: boolean) {
const filename = data.split("\n")[0].replace("[[", "").replace("]]", ""); const filename = data.split("\n")[0].replace("[[", "").replace("]]", "");
const content = data.replace(`[[${filename}]]\n`, ""); const content = data.replace(`[[${filename}]]\n`, "");
const image = useMemo(() => { const image = useMemo(() => {
// get image url from content (like: https://i.imgur.com/xxxxx.png) // get image url from content (like: https://i.imgur.com/xxxxx.png)
const match = content const match = content.match(/(https?:\/\/.*\.(?:png|jpg|jpeg|gif))/);
.toLowerCase() return match ? match[0] : "";
.match(/(https?:\/\/.*\.(?:png|jpg|jpeg|gif))/); }, [filename, content]);
const b64image = useMemo(() => {
// get base64 image from content (like: data:image/png;base64,xxxxx)
const match = content.match(/(data:image\/.*;base64,.*=)/);
return match ? match[0] : ""; return match ? match[0] : "";
}, [filename, content]); }, [filename, content]);
@ -38,12 +43,16 @@ export function parseFile(data: string, acceptDownload?: boolean) {
<File className={`mr-1`} /> <File className={`mr-1`} />
<span className={`name`}>{filename}</span> <span className={`name`}>{filename}</span>
<div className={`grow`} /> <div className={`grow`} />
{image ? ( {image || b64image ? (
<Button <Button
variant={`ghost`} variant={`ghost`}
size={`icon`} size={`icon`}
className={`download-action p-0 h-4 w-4`} className={`download-action p-0 h-4 w-4`}
onClick={async () => { onClick={async () => {
if (b64image) {
saveImageAsFile(filename, b64image);
return;
}
const res = await fetch(image); const res = await fetch(image);
saveBlobAsFile(filename, await res.blob()); saveBlobAsFile(filename, await res.blob());
}} }}
@ -57,6 +66,7 @@ export function parseFile(data: string, acceptDownload?: boolean) {
)} )}
</div> </div>
{image && <img src={image} className={`file-image`} alt={""} />} {image && <img src={image} className={`file-image`} alt={""} />}
{b64image && <img src={b64image} className={`file-image`} alt={""} />}
</div> </div>
); );
} }

View File

@ -50,6 +50,9 @@ func RegisterStaticRoute(engine *gin.Engine) {
// static files are in ~/app/dist // static files are in ~/app/dist
if !viper.GetBool("serve_static") { if !viper.GetBool("serve_static") {
engine.NoRoute(func(c *gin.Context) {
c.JSON(404, gin.H{"status": false, "message": "not found or method not allowed"})
})
return return
} }