Skip to content

Commit

Permalink
✨🐛Followed svg schema
Browse files Browse the repository at this point in the history
  • Loading branch information
carefree0910 committed Oct 5, 2023
1 parent 86fdbea commit a1f7f72
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 5 deletions.
8 changes: 7 additions & 1 deletion cfdraw/.web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ function App() {
setupOptions={{
isProd: false,
exportFn: ({ url, jpeg }) => fetchImage({ url, jpeg }),
uploadFn: async (blob) => {
uploadImageFn: async (blob) => {
return uploadImage(blob, { failed: async () => void 0 });
},
uploadSVGFn: async (svg) => {
return uploadImage(new Blob([svg], { type: "image/svg+xml" }), {
isSVG: true,
failed: async () => void 0,
});
},
setupBeforeBoard: () =>
waitUntil(() => !isUndefined(settingsStore.boardSettings)).then(() => {
const { styles, boardOptions, globalSettings, initialProject } = shallowCopy(
Expand Down
13 changes: 11 additions & 2 deletions cfdraw/.web/src/actions/uploadImage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { safeCall, Requests } from "@carefree0910/core";
import { safeCall, Requests, getImageSizeOf } from "@carefree0910/core";
import { Toast_Words, toastWord } from "@carefree0910/components";

import { userStore } from "@/stores/user";

type UploadImageOptions = {
isSVG?: boolean;
failed: (e: any) => Promise<void>;
};

Expand All @@ -17,7 +18,7 @@ export interface IUploadImageResponseData {

export async function uploadImage(
blob: Blob,
{ failed }: UploadImageOptions,
{ isSVG, failed }: UploadImageOptions,
): Promise<IUploadImageResponseData | void> {
return safeCall(
async () => {
Expand All @@ -29,13 +30,21 @@ export async function uploadImage(
image: blob,
userId: userStore.userId,
userJson: userStore.json,
isSVG: isSVG ? "1" : "0",
});
if (!res.success) {
toastWord("error", Toast_Words["upload-image-error-message"], {
appendix: ` - ${res.message}`,
});
return;
}
if (isSVG) {
const objURL = URL.createObjectURL(blob);
const { w, h } = await getImageSizeOf(objURL);
URL.revokeObjectURL(objURL);
res.data.w = w;
res.data.h = h;
}
return res.data;
},
{
Expand Down
13 changes: 12 additions & 1 deletion cfdraw/app/endpoints/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

from cfdraw import constants
from cfdraw.app.schema import IApp
from cfdraw.utils.server import save_svg
from cfdraw.utils.server import save_image
from cfdraw.utils.server import get_svg_response
from cfdraw.utils.server import get_image_response
from cfdraw.app.endpoints.base import IEndpoint

Expand Down Expand Up @@ -56,6 +58,7 @@ async def upload_image(
userJson: str,
meta: PngInfo,
base_url: str,
is_svg: bool,
audit: bool,
) -> ImageDataModel:
"""
Expand All @@ -64,6 +67,10 @@ async def upload_image(
* `FieldsMiddleware`, `contents` will be an `Image.Image` object.
"""

if is_svg:
if isinstance(contents, Image.Image):
raise ValueError("svg image should be uploaded as bytes")
return ImageDataModel(**save_svg(contents.decode(), base_url))
meta.add_text("userJson", userJson)
if isinstance(contents, Image.Image):
image = contents
Expand All @@ -83,6 +90,7 @@ async def upload_image(
image: UploadFile = File(),
userId: str = Form(),
userJson: Optional[str] = Form(None),
isSVG: str = Form("0"),
audit: bool = Form(True),
*,
request: Request,
Expand All @@ -92,7 +100,8 @@ async def upload_image(
contents = image.file.read()
if userJson is None:
userJson = json.dumps(dict(userId=userId))
args = contents, userJson, PngInfo(), base_url, audit
is_svg = isSVG == "1"
args = contents, userJson, PngInfo(), base_url, is_svg, audit
data = await ImageUploader.upload_image(*args)
except Exception as err:
logging.exception("failed to upload image")
Expand All @@ -111,6 +120,8 @@ async def fetch_image(data: FetchImageModel) -> Response:
**get_image_response_kwargs(),
)
async def get_image(file: str, jpeg: bool = False) -> Response:
if file.endswith(".svg"):
return get_svg_response(file)
return get_image_response(file, jpeg)


Expand Down
3 changes: 2 additions & 1 deletion cfdraw/plugins/middlewares/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ async def process(
upload = ImageUploader.upload_image
base_url = self.request.baseURL
user_json = self.request.get_user_json()
futures = [upload(im, user_json, meta, base_url, audit) for im in response]
args = user_json, meta, base_url, False, audit
futures = [upload(im, *args) for im in response]
urls = [data.dict() for data in await asyncio.gather(*futures)]
self.plugin.elapsed_times.upload = time.time() - t
return self.make_success(dict(type="image", value=urls))
Expand Down
24 changes: 24 additions & 0 deletions cfdraw/utils/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@
from cfdraw.config import get_config


def save_svg(svg: str, base_url: str) -> Dict[str, Any]:
config = get_config()
state = random.getstate()
random.seed()
path = config.upload_image_folder / f"{random_hash()}.svg"
random.setstate(state)
with path.open("w") as f:
f.write(svg)
base_url = base_url.rstrip("/")
url = f"{base_url}/{path.relative_to(config.upload_root_path).as_posix()}"
return dict(w=0, h=0, url=url)


def save_image(image: Image.Image, meta: PngInfo, base_url: str) -> Dict[str, Any]:
w, h = image.size
config = get_config()
Expand All @@ -30,6 +43,17 @@ def save_image(image: Image.Image, meta: PngInfo, base_url: str) -> Dict[str, An
return dict(w=w, h=h, url=url)


def get_svg_response(file: str) -> Response:
config = get_config()
try:
svg_path = config.upload_image_folder / file
with svg_path.open("r") as f:
content = f.read()
return Response(content=content, media_type="image/svg+xml")
except Exception as err:
raise_err(err)


def get_image(file: str, jpeg: bool = False) -> Image.Image:
config = get_config()
try:
Expand Down

0 comments on commit a1f7f72

Please sign in to comment.