Browse Source

Merge branch '0.1.8b' into fix/print-queue-time

MartinNYHC 3 tháng trước cách đây
mục cha
commit
cbb3b8c097
1 tập tin đã thay đổi với 50 bổ sung9 xóa
  1. 50 9
      backend/app/services/bambu_ftp.py

+ 50 - 9
backend/app/services/bambu_ftp.py

@@ -80,6 +80,9 @@ class BambuFTPClient:
     # Models that may need SSL mode fallback (try prot_p first, fall back to prot_c)
     # Models that may need SSL mode fallback (try prot_p first, fall back to prot_c)
     # These models have varying FTP SSL behavior depending on firmware version
     # These models have varying FTP SSL behavior depending on firmware version
     A1_MODELS = ("A1", "A1 Mini")
     A1_MODELS = ("A1", "A1 Mini")
+    # Chunk size for manual upload transfer (1MB)
+    # Larger chunks reduce overhead and work better with A1 printers
+    CHUNK_SIZE = 1024 * 1024
 
 
     # Cache for working FTP modes per printer IP
     # Cache for working FTP modes per printer IP
     # Maps IP -> "prot_p" or "prot_c"
     # Maps IP -> "prot_p" or "prot_c"
@@ -363,15 +366,37 @@ class BambuFTPClient:
 
 
             uploaded = 0
             uploaded = 0
 
 
-            def on_block(block: bytes):
-                nonlocal uploaded
-                uploaded += len(block)
-                if progress_callback:
-                    progress_callback(uploaded, file_size)
-
+            # Use manual transfer instead of storbinary() for A1 compatibility
+            # A1 printers have issues with storbinary's voidresp() hanging after transfer
             with open(local_path, "rb") as f:
             with open(local_path, "rb") as f:
                 logger.debug(f"FTP STOR command starting for {remote_path}")
                 logger.debug(f"FTP STOR command starting for {remote_path}")
-                self._ftp.storbinary(f"STOR {remote_path}", f, callback=on_block)
+                conn = self._ftp.transfercmd(f"STOR {remote_path}")
+
+                # Set explicit socket options for reliable transfer
+                conn.setblocking(True)
+                conn.settimeout(120)  # 2 minute timeout per chunk
+
+                try:
+                    while True:
+                        chunk = f.read(self.CHUNK_SIZE)
+                        if not chunk:
+                            logger.debug("FTP upload: final chunk reached")
+                            break
+
+                        conn.sendall(chunk)
+                        uploaded += len(chunk)
+                        logger.debug(f"FTP upload progress: {uploaded}/{file_size} bytes")
+
+                        if progress_callback:
+                            progress_callback(uploaded, file_size)
+
+                except OSError as e:
+                    logger.error(f"FTP connection lost during upload: {e}")
+                    conn.close()
+                    raise
+
+                conn.close()
+
             logger.info(f"FTP upload complete: {remote_path}")
             logger.info(f"FTP upload complete: {remote_path}")
             return True
             return True
         except ftplib.error_perm as e:
         except ftplib.error_perm as e:
@@ -399,8 +424,24 @@ class BambuFTPClient:
             return False
             return False
 
 
         try:
         try:
-            buffer = BytesIO(data)
-            self._ftp.storbinary(f"STOR {remote_path}", buffer)
+            # Use manual transfer instead of storbinary() for A1 compatibility
+            conn = self._ftp.transfercmd(f"STOR {remote_path}")
+            conn.setblocking(True)
+            conn.settimeout(120)
+
+            try:
+                # Send data in chunks
+                offset = 0
+                while offset < len(data):
+                    chunk = data[offset : offset + self.CHUNK_SIZE]
+                    conn.sendall(chunk)
+                    offset += len(chunk)
+            except OSError as e:
+                logger.error(f"FTP connection lost during upload_bytes: {e}")
+                conn.close()
+                raise
+
+            conn.close()
             return True
             return True
         except Exception:
         except Exception:
             return False
             return False