Android uygulamasından sunucuya dosya veya fotoğraf nasıl yüklenir?
Kısa cevap: POST yöntemiyle Content-Type: multipart/form-data kullanın (Retrofit + OkHttp) — dosyayı hazırlayın (veya InputStream → geçici dosya), ek alanlar için MultipartBody.Part ve RequestBody oluşturun, arka planda gönderin, ilerlemeyi gösterin, ağ hatalarını kontrol edin ve HTTPS kullanın.
Ne seçmeli ve backend ile hangi anlaşmalar gerekli?
Kod yazmadan önce backend ile şunları netleştirin:
- URL ve yöntem (örneğin POST /api/upload).
- Dosya için alan adı (file, image vb.).
- Gerekli ek alanlar (user_id, token, description).
- Maksimum boyut ve izin verilen MIME türleri.
- Başarılı yanıt formatı (JSON: url, id, size).
Sunucuyu kontrol ediyorsanız, istemciye multipart/form-data destekleyen bir endpoint sağlamak tercih edilir. Büyük dosyalar için pre-signed URL (S3/GCS) kullanmak ve doğrudan depolama alanına yüklemek daha iyidir.
Pratik uygulama (Kotlin, Retrofit + OkHttp)
- İzinler ve dosya alma
- Dosya seçimi için ACTION_OPEN_DOCUMENT (SAF) kullanın — yeni Android sürümlerinde READ_EXTERNAL_STORAGE gerektirmez.
- Kamera için — ACTION_IMAGE_CAPTURE + FileProvider, gerekirse runtime CAMERA iznini unutmayın.
- Uri üzerinden contentResolver.openInputStream(uri) ile açın ve context.cacheDir içindeki geçici bir dosyaya kopyalayın.
- Multipart hazırlığı
- File veya geçici dosyayı elde ettikten sonra: val requestFile = file.asRequestBody(mimeType.toMediaType()) val part = MultipartBody.Part.createFormData("file", file.name, requestFile) val desc = "Açıklama".toRequestBody("text/plain".toMediaType())
-
Retrofit API interface UploadApi { @Multipart @POST("upload") suspend fun uploadFile( @Part file: MultipartBody.Part, @Part("description") description: RequestBody ): Response
} -
Gönderim ve yanıt işleme
- Çağrıyı coroutine ile (IO Dispatcher) veya arka plan yüklemesi için WorkManager üzerinden gerçekleştirin.
- response.isSuccessful kontrolünü yapın ve hata mesajları için body() veya errorBody() ayrıştırın.
- Büyük dosyalar için OkHttpClient içinde zaman aşımlarını (connect/read/write) ayarlayın.
Yükleme ilerlemesi nasıl gösterilir?
writeTo(...) içinde gönderilen baytları sayan ve callback aracılığıyla UI'ı güncelleyen (Ana thread üzerinden) bir RequestBody sarmalayıcı oluşturun:
- UI'ı doğrudan writeTo içinden güncellemeyin — Handler veya ana akışa geçen bir completion callback kullanın.
- Çoklu dosyalar için bir kuyruk ve atomik durumlar (yükleniyor, başarılı, hata) uygulayın.
Büyük geçici dosyaları context.cacheDir içinde saklayın ve başarılı yüklemeden sonra temizleyin.
Hata yönetimi ve dayanıklılık
Sık karşılaşılan durumlar:
- Ağ yok: Anlaşılır bir mesaj ve "Tekrar Dene" butonu gösterin.
- Zaman aşımı: Üstel gecikme ile yeniden deneme önerin veya butonla tekrar deneyin.
- 4xx: Yetkilendirme/alanları kontrol edin — sunucudan gelen hata metnini gösterin.
- 5xx: Sunucu sorunu — daha sonra tekrar denemeyi önerin. Teknik olarak: Ağ hatalarını ve API hatalarını ayırın, günlüğe kaydedin (interceptor) ve UI'ı bloklamayın.
Güvenlik ve doğrulama
- Her zaman HTTPS kullanın.
- Gereksiz meta verileri (yollar, yerel tanımlayıcılar) göndermeyin.
- Tokenları güvenli şekilde saklayın (EncryptedSharedPreferences/Keystore).
- Sunucuda MIME türünü imzaya göre kontrol edin, boyutu ve formatları sınırlayın, istemci tarafı kontrole güvenmeyin.
Sık yapılan hatalar
- Yeniden boyutlandırma olmadan büyük resimlerin gönderilmesi → zaman aşımları ve yüksek veri tüketimi.
- Yanlış multipart alan adı → sunucudan 400/422 hatası.
- Android 10+ üzerinde Uri'yi doğrudan File olarak okumaya çalışmak — InputStream/SAF kullanın.
- RequestBody.writeTo içinde arka plan akışından UI güncellemesi yapmak.
SSS
- Uri'yi File'a kopyalamak gerekir mi? Genellikle evet: Birçok kütüphane File ile daha rahat çalışır ve ayrıca boyut ile adı belirlemek için gereklidir. Büyük dosyalar için belleğe tamamen okumadan stream etmek daha iyidir.
- Dosya JSON (Base64) olarak gönderilebilir mi? Gönderilebilir ancak kötüdür: Boyut ~%33 artar, CPU/bellek yükü yükselir; yalnızca çok küçük dosyalar için uygundur.
- Uygulamadan çıkıldığında arka planda nasıl yüklenir? WorkManager kullanın (özellikle cihaz yeniden başlatıldığında teslimatın garanti edilmesi gerekiyorsa).
Yığınınızı (Kotlin/Java, Retrofit/OkHttp veya saf OkHttp) ve kesin API sözleşmesini belirtirseniz — yapılandırmanıza uygun minimum çalışan kod örneğini paylaşabilirim.