feat: sending base64 image to backend

This is silly, but binary is apparently hard to do????
This commit is contained in:
2025-03-08 12:30:16 +00:00
parent d212584486
commit bf07c18fd7
5 changed files with 93 additions and 88 deletions

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -88,8 +89,6 @@ func main() {
return return
} }
fmt.Printf("%+v\n", image)
imageInfo, err := openAiClient.GetImageInfo(image.Image.ImageName, image.Image.Image) imageInfo, err := openAiClient.GetImageInfo(image.Image.ImageName, image.Image.Image)
if err != nil { if err != nil {
log.Println("2") log.Println("2")
@ -189,8 +188,21 @@ func main() {
return return
} }
image, err := io.ReadAll(r.Body) bodyData, err := io.ReadAll(r.Body)
fmt.Println(image) // TODO: check headers
contentType := r.Header.Get("Content-Type")
image := make([]byte, 0)
if contentType == "application/base64" {
base64.StdEncoding.Decode(image, bodyData)
} else if contentType == "application/oclet-stream" {
image = bodyData
} else {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Bruh, you need oclet stream or base64")
return
}
if err != nil { if err != nil {
log.Println("First case") log.Println("First case")

View File

@ -35,8 +35,6 @@ func removeImageToProcess(imageId string) error {
stmt := UserImagesToProcess.DELETE().WHERE(UserImagesToProcess.ID.EQ(UUID(id))) stmt := UserImagesToProcess.DELETE().WHERE(UserImagesToProcess.ID.EQ(UUID(id)))
fmt.Println(stmt.DebugSql())
_, err := stmt.Exec(db) _, err := stmt.Exec(db)
return err return err
@ -111,8 +109,6 @@ func GetImageToProcess(imageId string) (model.UserImagesToProcess, error) {
id := uuid.MustParse(imageId) id := uuid.MustParse(imageId)
stmt := UserImagesToProcess.SELECT(UserImagesToProcess.AllColumns).WHERE(UserImagesToProcess.ID.EQ(UUID(id))) stmt := UserImagesToProcess.SELECT(UserImagesToProcess.AllColumns).WHERE(UserImagesToProcess.ID.EQ(UUID(id)))
fmt.Println(stmt.DebugSql())
images := []model.UserImagesToProcess{} images := []model.UserImagesToProcess{}
err := stmt.Query(db, &images) err := stmt.Query(db, &images)
@ -138,8 +134,6 @@ func GetUserImages(userId string) ([]UserImagesWithInfo, error) {
id := uuid.MustParse(userId) id := uuid.MustParse(userId)
stmt := SELECT(UserImages.ID.AS("UserImagesWithInfo.ID"), Image.ID, Image.ImageName, ImageTags.AllColumns, ImageText.AllColumns, ImageLinks.AllColumns).FROM(UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID)).LEFT_JOIN(ImageTags, ImageTags.ImageID.EQ(UserImages.ID)).LEFT_JOIN(ImageText, ImageText.ImageID.EQ(UserImages.ID)).LEFT_JOIN(ImageLinks, ImageLinks.ImageID.EQ(UserImages.ID))).WHERE(UserImages.UserID.EQ(UUID(id))) stmt := SELECT(UserImages.ID.AS("UserImagesWithInfo.ID"), Image.ID, Image.ImageName, ImageTags.AllColumns, ImageText.AllColumns, ImageLinks.AllColumns).FROM(UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID)).LEFT_JOIN(ImageTags, ImageTags.ImageID.EQ(UserImages.ID)).LEFT_JOIN(ImageText, ImageText.ImageID.EQ(UserImages.ID)).LEFT_JOIN(ImageLinks, ImageLinks.ImageID.EQ(UserImages.ID))).WHERE(UserImages.UserID.EQ(UUID(id)))
fmt.Println(stmt.DebugSql())
images := []UserImagesWithInfo{} images := []UserImagesWithInfo{}
err := stmt.Query(db, &images) err := stmt.Query(db, &images)
@ -157,8 +151,6 @@ func SaveImageTags(imageId string, tags []string) ([]model.ImageTags, error) {
stmt.RETURNING(ImageTags.AllColumns) stmt.RETURNING(ImageTags.AllColumns)
fmt.Println(stmt.DebugSql())
imageTags := []model.ImageTags{} imageTags := []model.ImageTags{}
err := stmt.Query(db, &imageTags) err := stmt.Query(db, &imageTags)

View File

@ -7,6 +7,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"log"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -264,6 +265,7 @@ func parseOpenAiResponse(jsonResponse []byte) (ImageInfo, error) {
} }
if len(response.Choices) != 1 { if len(response.Choices) != 1 {
log.Println(string(jsonResponse))
return ImageInfo{}, errors.New("Expected exactly one choice.") return ImageInfo{}, errors.New("Expected exactly one choice.")
} }
@ -298,8 +300,6 @@ func (client OpenAiClient) GetImageInfo(imageName string, imageData []byte) (Ima
return ImageInfo{}, err return ImageInfo{}, err
} }
fmt.Println(string(jsonAiRequest))
request, err := client.getRequest(jsonAiRequest) request, err := client.getRequest(jsonAiRequest)
if err != nil { if err != nil {
return ImageInfo{}, err return ImageInfo{}, err
@ -315,6 +315,5 @@ func (client OpenAiClient) GetImageInfo(imageName string, imageData []byte) (Ima
return ImageInfo{}, err return ImageInfo{}, err
} }
fmt.Println(string(response))
return parseOpenAiResponse(response) return parseOpenAiResponse(response)
} }

View File

@ -9,11 +9,13 @@ export function ImageViewer() {
createEffect(() => { createEffect(() => {
// Listen for PNG processing events // Listen for PNG processing events
const unlisten = listen("png-processed", (event) => { const unlisten = listen("png-processed", (event) => {
console.log("Received processed PNG"); console.log("Received processed PNG", event);
const base64Data = event.payload as string; const base64Data = event.payload as string;
setLatestImage(`data:image/png;base64,${base64Data}`);
sendImage("test-image.png", base64Data); const urlImage = `data:image/png;base64,${base64Data}`;
setLatestImage(urlImage);
sendImage("test-image.png", urlImage);
}); });
return () => { return () => {

View File

@ -1,97 +1,97 @@
import { import {
array, array,
InferOutput, InferOutput,
null as Null, null as Null,
nullable, nullable,
object, object,
parse, parse,
pipe, pipe,
string, string,
uuid, uuid,
} from "valibot"; } from "valibot";
type BaseRequestParams = Partial<{ type BaseRequestParams = Partial<{
path: string; path: string;
body: RequestInit["body"]; body: RequestInit["body"];
method: "GET" | "POST"; method: "GET" | "POST";
}>; }>;
const getBaseRequest = ({ path, body, method }: BaseRequestParams): Request => { const getBaseRequest = ({ path, body, method }: BaseRequestParams): Request => {
return new Request(`http://localhost:3040/${path}`, { return new Request(`http://localhost:3040/${path}`, {
headers: { userId: "fcc22dbb-7792-4595-be8e-d0439e13990a" }, headers: { userId: "fcc22dbb-7792-4595-be8e-d0439e13990a" },
body, body,
method, method,
}); });
}; };
const sendImageResponseValidator = object({ const sendImageResponseValidator = object({
ID: pipe(string(), uuid()), ID: pipe(string(), uuid()),
ImageID: pipe(string(), uuid()), ImageID: pipe(string(), uuid()),
UserID: pipe(string(), uuid()), UserID: pipe(string(), uuid()),
}); });
export const sendImage = async ( export const sendImage = async (
imageName: string, imageName: string,
image: BlobPart, image: BlobPart,
): Promise<InferOutput<typeof sendImageResponseValidator>> => { ): Promise<InferOutput<typeof sendImageResponseValidator>> => {
const data = new Blob([image]); const data = new Blob([image]);
const request = getBaseRequest({ const request = getBaseRequest({
path: `image/${imageName}`, path: `image/${imageName}`,
body: data, body: data,
method: "POST", method: "POST",
}); });
request.headers.set("Content-Type", "aplication/oclet-stream"); request.headers.set("Content-Type", "aplication/base64");
const res = await fetch(request).then((res) => res.json()); const res = await fetch(request).then((res) => res.json());
return parse(sendImageResponseValidator, res); return parse(sendImageResponseValidator, res);
}; };
const getUserImagesResponseValidator = array( const getUserImagesResponseValidator = array(
object({ object({
ID: pipe(string(), uuid()), ID: pipe(string(), uuid()),
Image: object({ Image: object({
ID: pipe(string(), uuid()), ID: pipe(string(), uuid()),
ImageName: string(), ImageName: string(),
Image: Null(), Image: Null(),
}), }),
Tags: nullable( Tags: nullable(
array( array(
object({ object({
ID: pipe(string(), uuid()), ID: pipe(string(), uuid()),
Tag: string(), Tag: string(),
ImageID: pipe(string(), uuid()), ImageID: pipe(string(), uuid()),
}), }),
), ),
), ),
Links: nullable( Links: nullable(
array( array(
object({ object({
ID: pipe(string(), uuid()), ID: pipe(string(), uuid()),
Links: string(), Links: string(),
ImageID: pipe(string(), uuid()), ImageID: pipe(string(), uuid()),
}), }),
), ),
), ),
Text: nullable( Text: nullable(
array( array(
object({ object({
ID: pipe(string(), uuid()), ID: pipe(string(), uuid()),
ImageText: string(), ImageText: string(),
ImageID: pipe(string(), uuid()), ImageID: pipe(string(), uuid()),
}), }),
), ),
), ),
}), }),
); );
export const getUserImages = async (): Promise< export const getUserImages = async (): Promise<
InferOutput<typeof getUserImagesResponseValidator> InferOutput<typeof getUserImagesResponseValidator>
> => { > => {
const request = getBaseRequest({ path: "image" }); const request = getBaseRequest({ path: "image" });
const res = await fetch(request).then((res) => res.json()); const res = await fetch(request).then((res) => res.json());
return parse(getUserImagesResponseValidator, res); return parse(getUserImagesResponseValidator, res);
}; };