For those with an inputStream, you can upload inputStream using Multipart
.
@Multipart
@POST("pictures")
suspend fun uploadPicture(
@Part part: MultipartBody.Part
): NetworkPicture
Then in perhaps your repository class:
suspend fun upload(inputStream: InputStream) {
val part = MultipartBody.Part.createFormData(
"pic",
"myPic",
RequestBody.create(
MediaType.parse("image/*"),
inputStream.readBytes()
)
)
uploadPicture(part)
}
If your backend does not allow multipart, you can convert the input stream into bytes and send the byte array as the request body, like so.
// In your service
@PUT
suspend fun s3Upload(
@Header("Content-Type") mime: String,
@Url uploadUrl: String,
@Body body: RequestBody
)
// In your repository
val body = RequestBody.create(
MediaType.parse("application/octet"),
inputStream.readBytes()
)
networkService.s3Upload(mime, url, body)
To get an input stream you can do something like so.
In your fragment or activity, you need to create an image picker that returns an InputStream
. The advantage of an InputStream is that it can be used for files on the cloud like google drive and dropbox.
Call pickImagesLauncher.launch("image/*")
from a View.OnClickListener
or onOptionsItemSelected
. (See Activity Result APIs).
private val pickImagesLauncher = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri ->
uri?.let {
val stream = contentResolver.openInputStream(it)
itemViewModel.uploadPicture(stream)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
btn.setOnClickListener {
pickImagesLauncher.launch("image/*")
}
}