I'm trying to send an image to extract text from it using https://api-ninjas.com/api/imagetotext. I still get an HTTP 400 Error though and couldn't figure out why! I have an image in my assets folder and I should receive a list of words from the API as mentioned in the link. Any hints about how to get a appropriate error or to fix it would be great. My Code is:
data class Word(
val bounding_box: BoundingBox,
val text: String
)
data class BoundingBox(
val x1: Int,
val x2: Int,
val y1: Int,
val y2: Int
)
FileApi.kt
import com.example.misinfo.retrofitfileupload.dto.Word
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
interface FileApi {
@Multipart
@POST("/v1/imagetotext")
suspend fun uploadImage(
@Part image: MultipartBody.Part,
): Call<List<Word>>
companion object {
private val client = OkHttpClient.Builder().build()
val instance by lazy {
Retrofit.Builder()
//TODO: add some API url
.baseUrl("https://api.api-ninjas.com/")
.client(client) // add a client instance here, e.g. OkHttpClient
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(FileApi::class.java)
}
}
}
FileRepository.kt
import android.util.Log
import com.example.misinfo.retrofitfileupload.dto.Word
import okhttp3.MultipartBody
import java.io.File
import java.io.IOException
import okhttp3.RequestBody.Companion.asRequestBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.HttpException
import retrofit2.Response
class FileRepository {
suspend fun uploadImage(file: File): Boolean {
var res = false
try {
FileApi.instance.uploadImage(
image = MultipartBody.Part
.createFormData(
"image",
file.name,
file.asRequestBody()
)
).enqueue(
object : Callback<List<Word>> {
override fun onFailure(call: Call<List<Word>>, t: Throwable) {
Log.e("API Request", "I got an error and i don't know why :(")
}
override fun onResponse( call: Call<List<Word>>, response: Response<List<Word>>) {
val responseBody = response.body()
Log.e("API Request", responseBody.toString())
}
}
)
res = true
return res
} catch (e: IOException) {
e.printStackTrace()
return res
} catch (e: HttpException) {
e.printStackTrace()
return res
} finally {
Log.e("API Request", res.toString())
}
}
}
FileViewModel.kt
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.misinfo.retrofitfileupload.FileRepository
import kotlinx.coroutines.launch
import java.io.File
class FileViewModel(
private val repository: FileRepository= FileRepository()
): ViewModel() {
fun uploadImage(file: File){
viewModelScope.launch {
repository.uploadImage(file)
}
}
}
MainActicity.kt
class MainActivity : ComponentActivity() {
class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
println("Clicked on Pip Action")
}
}
private val isPipSupported by lazy {
packageManager.hasSystemFeature(
PackageManager.FEATURE_PICTURE_IN_PICTURE
)
}
private var viewBounds = Rect()
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MisInfoTheme {
//ApplicationSwitcher()
val viewModel = viewModel<FileViewModel>()
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Button(onClick = {
val file = File(cacheDir, "img.png")
file.createNewFile()
file.outputStream().use {
assets.open("img.png").copyTo(it)
}
viewModel.uploadImage(file)
}) {
Text(text = "Upload image")
}
}
}
}
}
}
CodePudding user response:
HTTP 400 Bad Request so I guess the problem here as you trying to send with the wrong path as you see here you setting your POST endpoint wrong it shouldn't start with the "/" remove this and it should work fine I guess
@Multipart
@POST("v1/imagetotext")
suspend fun uploadImage(
@Part image: MultipartBody.Part,
): Call<List<Word>>
CodePudding user response:
I solved the problem by adding a header to my post request.
interface FileApi {
@Headers("X-Api-Key: add your header")
@Multipart
@POST("v1/imagetotext")
fun uploadImage(
@Part image: MultipartBody.Part,
): Call<List<Word>>
companion object {
private val client = OkHttpClient.Builder().build()
val instance by lazy {
Retrofit.Builder()
//TODO: add some API url
.baseUrl("https://api.api-ninjas.com/")
.client(client) // add a client instance here, e.g. OkHttpClient
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(FileApi::class.java)
}
}
}