fix(ocr): Fix mobile file upload ERR_NETWORK on Android/iOS
Clone file to memory immediately after selection to avoid SnapshotState invalidation in W3C File API. Android/iOS browsers invalidate File object references after accessing properties (name, size, type). See: https://issues.chromium.org/40703873 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
24
CLAUDE.md
24
CLAUDE.md
@@ -420,6 +420,30 @@ const response = await api.get('/endpoint');
|
|||||||
→ **Frontend**: Clear node_modules, check Node.js version (16+), Vite auto-ports
|
→ **Frontend**: Clear node_modules, check Node.js version (16+), Vite auto-ports
|
||||||
→ **Database**: Verify SSH tunnel, Oracle listener, credentials, test `/health`
|
→ **Database**: Verify SSH tunnel, Oracle listener, credentials, test `/health`
|
||||||
|
|
||||||
|
### Known Issues & Fixes
|
||||||
|
|
||||||
|
#### Mobile File Upload ERR_NETWORK (Android/iOS)
|
||||||
|
**Problem**: File uploads (OCR, attachments) fail with `ERR_NETWORK` (status 0) on mobile browsers, but work on desktop.
|
||||||
|
|
||||||
|
**Cause**: Android/iOS browsers invalidate File object references after accessing properties (`file.name`, `file.size`, `file.type`) due to **SnapshotState** in the W3C File API. See [Chromium Bug #40703873](https://issues.chromium.org/40703873).
|
||||||
|
|
||||||
|
**Solution**: Clone the file into memory immediately after selection, before accessing any properties:
|
||||||
|
```javascript
|
||||||
|
const handleFile = async (file) => {
|
||||||
|
// Validations first...
|
||||||
|
|
||||||
|
// FIX: Clone file to memory to avoid SnapshotState invalidation
|
||||||
|
const arrayBuffer = await file.arrayBuffer()
|
||||||
|
const clonedFile = new File([arrayBuffer], file.name, {
|
||||||
|
type: file.type,
|
||||||
|
lastModified: file.lastModified
|
||||||
|
})
|
||||||
|
selectedFile.value = clonedFile
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Applied in**: `src/modules/data-entry/components/ocr/OCRUploadZone.vue`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔧 Tech Stack
|
## 🔧 Tech Stack
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ const onFileSelected = (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFile = (file) => {
|
const handleFile = async (file) => {
|
||||||
// Validate file type
|
// Validate file type
|
||||||
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf']
|
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf']
|
||||||
if (!allowedTypes.includes(file.type)) {
|
if (!allowedTypes.includes(file.type)) {
|
||||||
@@ -232,9 +232,25 @@ const handleFile = (file) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error.value = null
|
error.value = null
|
||||||
|
|
||||||
|
// FIX pentru Android: Clonăm fișierul în memorie IMEDIAT după selectare
|
||||||
|
// pentru a evita invalidarea referinței de către browser (SnapshotState issue)
|
||||||
|
// See: https://issues.chromium.org/40703873
|
||||||
|
try {
|
||||||
|
const arrayBuffer = await file.arrayBuffer()
|
||||||
|
const clonedFile = new File([arrayBuffer], file.name, {
|
||||||
|
type: file.type,
|
||||||
|
lastModified: file.lastModified
|
||||||
|
})
|
||||||
|
selectedFile.value = clonedFile
|
||||||
|
emit('file-selected', clonedFile)
|
||||||
|
} catch (e) {
|
||||||
|
// Fallback pentru browsere care nu suportă arrayBuffer
|
||||||
|
console.warn('File clone failed, using original:', e)
|
||||||
selectedFile.value = file
|
selectedFile.value = file
|
||||||
emit('file-selected', file)
|
emit('file-selected', file)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const processOCR = async () => {
|
const processOCR = async () => {
|
||||||
if (!selectedFile.value) return
|
if (!selectedFile.value) return
|
||||||
|
|||||||
Reference in New Issue
Block a user