diff --git a/DEBUG_UPLOAD_FILE.md b/DEBUG_UPLOAD_FILE.md
new file mode 100644
index 00000000..5fda9054
--- /dev/null
+++ b/DEBUG_UPLOAD_FILE.md
@@ -0,0 +1,170 @@
+# Debug Guide: Upload File Android vs iOS
+
+## ๐ฑ Problem
+- โ
Upload **IMAGE** berhasil di iOS dan Android
+- โ Upload **PDF** gagal di Android dengan error: `Status: 400 Bad Request`
+
+## ๐ Root Cause (DITEMUKAN!)
+
+### **Masalah MIME Type PDF**
+Dari log upload:
+```
+File details:
+ - Name: 154ce3b0-6fc0-4a39-9e09-3f9aa2b19300.pdf
+ - Type: image/pdf โ โ SALAH!
+ - Size: 26534 bytes
+```
+
+**Yang benar:**
+- โ `image/pdf` (salah - tidak ada MIME type ini)
+- โ
`application/pdf` (benar - standard MIME type untuk PDF)
+
+### **Kenapa Terjadi?**
+Mobile app (Android) salah set MIME type saat mengirim file PDF. Kemungkinan:
+1. File picker/set MIME type salah di mobile code
+2. Android WebView auto-detect MIME type incorrectly
+3. Mobile app hardcoded MIME type yang salah
+
+## ๐ ๏ธ Solusi yang Sudah Diterapkan
+
+### File: `src/app/api/mobile/file/route.ts`
+
+**Fix #1: Safe JSON Parsing**
+- โ
Cek response sebagai text dulu, lalu parse JSON
+- โ
Handle Content-Type yang salah dari external storage
+
+**Fix #2: MIME Type Override (LATEST)**
+- โ
Deteksi file PDF dari extension (.pdf)
+- โ
Override MIME type ke `application/pdf` jika salah
+- โ
Rebuild FormData dengan file yang sudah difix
+
+**Code:**
+```typescript
+// Jika file PDF tapi type bukan application/pdf, fix it
+if (fileName.endsWith(".pdf") && originalType !== "application/pdf") {
+ console.log("โ ๏ธ WARNING: PDF file has wrong MIME type:", originalType);
+ console.log("๐ง Overriding to: application/pdf");
+
+ // Create new File with correct MIME type
+ const buffer = await file.arrayBuffer();
+ fixedFile = new File([buffer], file.name, {
+ type: "application/pdf",
+ lastModified: file.lastModified,
+ });
+
+ // Rebuild formData with fixed file
+ formData.set("file", fixedFile);
+}
+```
+
+## ๐งช Cara Testing
+
+### 1. **Test Upload dari Android**
+Coba upload file PDF dari Android dan perhatikan log di terminal:
+
+```bash
+# Log yang akan muncul:
+=== UPLOAD REQUEST START ===
+dirId: xxx
+File details:
+ - Name: dokumen.pdf
+ - Type: application/pdf
+ - Size: 1234567 bytes
+ - Size (KB): 1205.63
+===========================
+Directory key: xxx
+=== EXTERNAL STORAGE RESPONSE ===
+Status: 400
+Status Text: Bad Request
+Content-Type: text/html; charset=utf-8
+=================================
+=== ERROR: Non-JSON Response ===
+Response text: Unsupported file format...
+=================================
+```
+
+### 2. **Informasi yang Perlu Dicari:**
+Dari log di atas, perhatikan:
+- **File size** โ Berapa MB? (mungkin terlalu besar?)
+- **File type** โ `application/pdf` atau yang lain?
+- **External storage response** โ Status code & message?
+- **Error text** โ Apa yang dikembalikan server external?
+
+### 3. **Compare iOS vs Android**
+Upload file yang sama dari iOS dan Android, bandingkan log-nya.
+
+## ๐ Expected Log Output
+
+### โ
Success Case:
+```
+=== UPLOAD REQUEST START ===
+dirId: investment
+File details:
+ - Name: proposal.pdf
+ - Type: application/pdf
+ - Size: 524288 bytes
+ - Size (KB): 512.00
+===========================
+Directory key: investment
+=== EXTERNAL STORAGE RESPONSE ===
+Status: 200
+Status Text: OK
+Content-Type: application/json
+=================================
+โ
Upload SUCCESS
+```
+
+### โ Failed Case (Non-JSON Response):
+```
+=== UPLOAD REQUEST START ===
+dirId: investment
+File details:
+ - Name: proposal.pdf
+ - Type: application/pdf
+ - Size: 5242880 bytes โ Mungkin terlalu besar?
+ - Size (KB): 5120.00
+===========================
+=== EXTERNAL STORAGE RESPONSE ===
+Status: 413 โ Payload Too Large?
+Content-Type: text/html
+=================================
+=== ERROR: Non-JSON Response ===
+Response text:
413 Request Entity Too Large
+=================================
+```
+
+## ๐ง Next Steps (Setelah Testing)
+
+Berdasarkan log, kita bisa identify masalahnya:
+
+### **Jika masalah FILE SIZE:**
+- Tambahkan limit validation di frontend
+- Compress PDF sebelum upload
+- Increase external storage limit
+
+### **Jika masalah FILE FORMAT:**
+- Validate file type sebelum upload
+- Convert format jika perlu
+- Update external storage allowed formats
+
+### **Jika masalah NETWORK/HEADERS:**
+- Check user-agent differences
+- Validate Authorization header
+- Check CORS settings
+
+## ๐ Checklist Testing
+- [ ] Test upload PDF kecil (< 1MB) dari Android
+- [ ] Test upload PDF besar (> 5MB) dari Android
+- [ ] Test upload PDF dari iOS (baseline)
+- [ ] Compare log output iOS vs Android
+- [ ] Check file type yang dikirim
+- [ ] Check file size yang dikirim
+- [ ] Check response dari external storage
+
+## ๐ฏ Goal
+Dari log yang detail, kita bisa tahu **exact reason** kenapa Android fail, lalu fix dengan tepat.
+
+---
+
+**Last Updated:** 2026-04-14
+**Status:** โ
Logging added, ready for testing
diff --git a/src/app/(support)/support-center/page.tsx b/src/app/(support)/support-center/page.tsx
index 9b23a078..9aefdc16 100644
--- a/src/app/(support)/support-center/page.tsx
+++ b/src/app/(support)/support-center/page.tsx
@@ -98,7 +98,7 @@ export default function SupportCenter() {
Support Center
- Send us a message and we'll get back to you as soon as possible.
+ Send us a message and we'll get back to you as soon as possible.
diff --git a/src/app/api/mobile/file/route.ts b/src/app/api/mobile/file/route.ts
index b3809d93..d8092876 100644
--- a/src/app/api/mobile/file/route.ts
+++ b/src/app/api/mobile/file/route.ts
@@ -2,14 +2,50 @@ import { funGetDirectoryNameByValue } from "@/app_modules/_global/fun/get";
import { NextResponse } from "next/server";
export async function POST(request: Request) {
- const formData = await request.formData();
- const dirId = formData.get("dirId");
-
- const keyOfDirectory = await funGetDirectoryNameByValue({
- value: dirId as string,
- });
-
try {
+ const formData = await request.formData();
+ const dirId = formData.get("dirId");
+ const file = formData.get("file") as File | null;
+
+ // === LOGGING: Request Details ===
+ console.log("=== UPLOAD REQUEST START ===");
+ console.log("dirId:", dirId);
+ console.log("File details:");
+ console.log(" - Name:", file?.name);
+ console.log(" - Type:", file?.type);
+ console.log(" - Size:", file?.size, "bytes");
+ console.log(" - Size (KB):", file ? (file.size / 1024).toFixed(2) : "N/A");
+ console.log("===========================");
+
+ // FIX: Override MIME type jika salah (mobile app kadang kirim image/pdf)
+ let fixedFile = file;
+ if (file) {
+ const fileName = file.name.toLowerCase();
+ const originalType = file.type.toLowerCase();
+
+ // Jika file PDF tapi type bukan application/pdf, fix it
+ if (fileName.endsWith(".pdf") && originalType !== "application/pdf") {
+ console.log("โ ๏ธ WARNING: PDF file has wrong MIME type:", originalType);
+ console.log("๐ง Overriding to: application/pdf");
+
+ // Create new File with correct MIME type
+ const buffer = await file.arrayBuffer();
+ fixedFile = new File([buffer], file.name, {
+ type: "application/pdf",
+ lastModified: file.lastModified,
+ });
+
+ // Rebuild formData with fixed file
+ formData.set("file", fixedFile);
+ }
+ }
+
+ const keyOfDirectory = await funGetDirectoryNameByValue({
+ value: dirId as string,
+ });
+
+ console.log("Directory key:", keyOfDirectory);
+
const res = await fetch("https://wibu-storage.wibudev.com/api/upload", {
method: "POST",
body: formData,
@@ -18,9 +54,70 @@ export async function POST(request: Request) {
},
});
- const dataRes = await res.json();
+ // === LOGGING: Response Details ===
+ console.log("=== EXTERNAL STORAGE RESPONSE ===");
+ console.log("Status:", res.status);
+ console.log("Status Text:", res.statusText);
+ console.log("Content-Type:", res.headers.get("content-type"));
+ console.log("=================================");
+
+ // Cek content-type sebelum parse JSON
+ const contentType = res.headers.get("content-type") || "";
+ let dataRes;
+
+ // Try parse JSON untuk semua response (beberapa server salah set content-type)
+ try {
+ const rawResponse = await res.text();
+
+ // Coba parse sebagai JSON
+ try {
+ dataRes = JSON.parse(rawResponse);
+ console.log("โ
Successfully parsed response as JSON");
+ } catch {
+ // Bukan JSON - gunakan raw text
+ console.log("โ ๏ธ Response is not JSON, using raw text");
+
+ if (res.ok) {
+ // Success tapi bukan JSON - return success response
+ return NextResponse.json(
+ {
+ success: true,
+ message: "Success upload file " + keyOfDirectory,
+ },
+ { status: 200 }
+ );
+ } else {
+ return NextResponse.json(
+ {
+ success: false,
+ message: "Upload failed",
+ error: rawResponse.substring(0, 500),
+ fileDetails: {
+ name: file?.name,
+ type: file?.type,
+ size: file?.size,
+ }
+ },
+ { status: res.status || 400 }
+ );
+ }
+ }
+ } catch (readError) {
+ console.log("โ Failed to read response body");
+ console.log("Read error:", (readError as Error).message);
+
+ return NextResponse.json(
+ {
+ success: false,
+ message: "Failed to read response",
+ reason: (readError as Error).message,
+ },
+ { status: 500 }
+ );
+ }
if (res.ok) {
+ console.log("โ
Upload SUCCESS");
return NextResponse.json(
{
success: true,
@@ -30,20 +127,34 @@ export async function POST(request: Request) {
{ status: 200 }
);
} else {
- const errorText = await res.text();
- console.log(`Failed upload ${keyOfDirectory}: ${errorText}`);
+ console.log("โ Upload FAILED");
+ console.log("Response:", dataRes);
+
+ const errorMessage = dataRes.message || dataRes.error || JSON.stringify(dataRes);
return NextResponse.json(
- { success: false, message: errorText },
- { status: 400 }
+ {
+ success: false,
+ message: errorMessage || "Upload failed",
+ fileDetails: {
+ name: file?.name,
+ type: file?.type,
+ size: file?.size,
+ }
+ },
+ { status: res.status || 400 }
);
}
} catch (error) {
- console.log("Error upload >>", (error as Error).message || error);
+ console.log("=== CATCH ERROR ===");
+ console.log("Error:", (error as Error).message);
+ console.log("Stack:", (error as Error).stack);
+ console.log("===================");
+
return NextResponse.json(
{
success: false,
message: "Failed upload file",
- reason: (error as Error).message || error,
+ reason: (error as Error).message || "Unknown error",
},
{ status: 500 }
);
diff --git a/src/app/api/mobile/forum/[id]/preview-report-posting/route.ts b/src/app/api/mobile/forum/[id]/preview-report-posting/route.ts
index b68db0eb..ea671197 100644
--- a/src/app/api/mobile/forum/[id]/preview-report-posting/route.ts
+++ b/src/app/api/mobile/forum/[id]/preview-report-posting/route.ts
@@ -1,3 +1,4 @@
+import { prisma } from "@/lib";
import { NextResponse } from "next/server";
export async function GET(