Binary uploader works too.
This commit is contained in:
@@ -6,13 +6,16 @@ from uuid import UUID
|
|||||||
import mimetypes
|
import mimetypes
|
||||||
import logging
|
import logging
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
|
import base64
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from packetserver.http.dependencies import get_current_http_user
|
from packetserver.http.dependencies import get_current_http_user
|
||||||
from packetserver.http.auth import HttpUser
|
from packetserver.http.auth import HttpUser
|
||||||
from packetserver.http.database import DbDependency
|
from packetserver.http.database import DbDependency
|
||||||
from packetserver.server.objects import Object
|
from packetserver.server.objects import Object
|
||||||
from packetserver.server.users import User
|
from packetserver.server.users import User
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
router = APIRouter(prefix="/api/v1", tags=["objects"])
|
router = APIRouter(prefix="/api/v1", tags=["objects"])
|
||||||
|
|
||||||
@@ -186,3 +189,68 @@ async def create_text_object(
|
|||||||
created_at=new_object.created_at,
|
created_at=new_object.created_at,
|
||||||
modified_at=new_object.modified_at
|
modified_at=new_object.modified_at
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class BinaryObjectCreate(BaseModel):
|
||||||
|
data_base64: str
|
||||||
|
name: Optional[str] = None
|
||||||
|
private: bool = True
|
||||||
|
|
||||||
|
@router.post("/objects/binary", response_model=ObjectSummary)
|
||||||
|
async def create_binary_object(
|
||||||
|
payload: BinaryObjectCreate,
|
||||||
|
db: DbDependency,
|
||||||
|
current_user: HttpUser = Depends(get_current_http_user)
|
||||||
|
):
|
||||||
|
username = current_user.username
|
||||||
|
|
||||||
|
# Decode base64
|
||||||
|
try:
|
||||||
|
content = base64.b64decode(payload.data_base64, validate=True)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=400, detail="Invalid base64 encoding")
|
||||||
|
|
||||||
|
if not content:
|
||||||
|
raise HTTPException(status_code=400, detail="Binary content cannot be empty")
|
||||||
|
|
||||||
|
obj_name = (payload.name or "binary_object.bin").strip()
|
||||||
|
if len(obj_name) > 300:
|
||||||
|
raise HTTPException(status_code=400, detail="Object name too long (max 300 chars)")
|
||||||
|
if not obj_name:
|
||||||
|
raise HTTPException(status_code=400, detail="Invalid object name")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with db.transaction() as conn:
|
||||||
|
root = conn.root()
|
||||||
|
user = User.get_user_by_username(username, root)
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(status_code=404, detail="User not found")
|
||||||
|
|
||||||
|
# Pass bytes → forces binary=True
|
||||||
|
new_object = Object(name=obj_name, data=content)
|
||||||
|
new_object.private = payload.private
|
||||||
|
|
||||||
|
obj_uuid = new_object.write_new(db, username=username)
|
||||||
|
|
||||||
|
logging.info(f"User {username} created binary object {obj_uuid} ({obj_name}, {len(content)} bytes via base64)")
|
||||||
|
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Binary object creation failed for {username}: {e}\n{format_exc()}")
|
||||||
|
raise HTTPException(status_code=500, detail="Failed to create binary object")
|
||||||
|
|
||||||
|
# Build summary
|
||||||
|
content_type, _ = mimetypes.guess_type(new_object.name)
|
||||||
|
if content_type is None:
|
||||||
|
content_type = "application/octet-stream" # always safe for binary
|
||||||
|
|
||||||
|
return ObjectSummary(
|
||||||
|
uuid=obj_uuid,
|
||||||
|
name=new_object.name,
|
||||||
|
binary=new_object.binary, # should be True
|
||||||
|
size=new_object.size,
|
||||||
|
content_type=content_type,
|
||||||
|
private=new_object.private,
|
||||||
|
created_at=new_object.created_at,
|
||||||
|
modified_at=new_object.modified_at
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user