Upload from android gallery to Server
from the CommonsWare Community archivesAt June 9, 2020, 5:46am, brainy15mca asked:
FIrst, I have to apologize for posting this here instead of the Android Development board - I have bought subscription but for whatever reason it’s not updated here on the board - can you please check what’s going on? (please move this in the Android Development board)
I am trying to upload files from android device to server in order to that I fetched URI like
suspend fun listVideos(): List<VideoModel>? =
withContext(Dispatchers.IO) {
val resolver = context.contentResolver
resolver.query(collection, PROJECTION, null, null, SORT_ORDER)
?.use { cursor ->
cursor.mapToList {
VideoModel(
it.getLong(0),
it.getString(1),
it.getString(2),
it.getString(3)
)
}
}
}
after that I created InputStreamRequestBody:
fun prepareFilePart(partName: String, uri: Uri, context: Context, name: String): MultipartBody.Part {
val inputStream = context.contentResolver.openInputStream(uri)
val requestBody: RequestBody =
RequestBodyUtil.create(MediaType.parse(context.contentResolver.getType(uri)), inputStream)
return MultipartBody.Part.createFormData(partName, name, requestBody)
}
Here is retrofit stuff:
public interface PlatformGroupPostService {
@Multipart
@POST("brainy/api/v0/post")
Observable<NewGroupAPIResponse> createPost(@Part("postData") RequestBody postData,
@Part MultipartBody.Part attachments);
}
But on server side I am always getting null file reference
Kindly suggest what could be the best way to achieve this feature
At June 9, 2020, 10:42am, mmurphy replied:
You have to request access to post to this board on the Warescription site, and I have to manually grant that access. That has now all been taken care of.
I do not know what RequestBodyUtil
is. The InputStreamRequestBody
that I point people to is this one (see the second listing in that GitHub issue comment). It works off of a Uri
and a ContentResolver
, as OkHttp may need to open the stream multiple times (see other discussion in that GitHub issue).
Personally, I have never needed to upload anything using @Part
so I have not needed to use that InputStreamRequestBody
. However, this topic is coming up enough that I may need to find some Web service API that needs this stuff, just so I can write a complete example of the process…
Regardless, I would try the InputStreamRequestBody
that I linked to and see if that changes anything for you.
At June 10, 2020, 4:01pm, brainy15mca replied:
I followed you and used this class:
public class InputStreamRequestBody extends RequestBody {
private final MediaType contentType;
private final ContentResolver contentResolver;
private final Uri uri;
public InputStreamRequestBody(MediaType contentType, ContentResolver contentResolver, Uri uri) {
if (uri == null) throw new NullPointerException("uri == null");
this.contentType = contentType;
this.contentResolver = contentResolver;
this.uri = uri;
}
@Nullable
@Override
public MediaType contentType() {
return contentType;
}
@Override
public long contentLength() {
return -1;
}
@Override
public void writeTo(@NonNull BufferedSink sink) throws IOException {
try (Source source = Okio.source(contentResolver.openInputStream(uri))) {
sink.writeAll(source);
}
}
}
But somehow this feature screwed me alot dont have idea, what to do now, could you please enlighten me
At June 10, 2020, 4:11pm, brainy15mca replied:
also if you want I can share mine Web Service API
At June 10, 2020, 5:39pm, mmurphy replied:
I do not know what “screwed me alot” means.
At June 10, 2020, 5:57pm, brainy15mca replied:
Sorry it was my bad, It meant like I am stuck since last 6 days without any clue, just exploring different blogs and stackoverflow and try to implement different-2 solution
At June 10, 2020, 6:46pm, mmurphy replied:
You might consider running an experiment:
- Create a file in
getFilesDir()
- Try uploading that file using more conventional
RequestBody
options
If that fails, then my guess is that there is some disconnect between your Retrofit definition and what the server is expecting.
If that succeeds, then you know the problem is tied to trying to upload from the Uri
. Worst-case, you can copy the content identified by the Uri
to a file, then upload the file. I have not had to do this sort of multipart upload personally.
More generally: your original question was very well-written! But, follow-up questions need that same level of care. Saying “screwed me alot” does not help anyone help you. Providing technical details of what you tried and what you are seeing might help others help you.
At June 10, 2020, 6:51pm, brainy15mca replied:
You are right will take care, finally I have done that things, Now I am able to upload multiple video from android gallery to my server . Issue have been resolved.
As you told some disconnection between retrofit and server : Its 100% right in my case. I had put wrong multi part name here
MultipartBody.Part.createFormData(partName, name, requestBody)
along With:
val requestBody: RequestBody = RequestBody.create(
MediaType.parse(context.contentResolver.getType(uri)),
getBytes(context.contentResolver.openInputStream(uri))
)
@Throws(IOException::class)
fun getBytes(inputStream: InputStream?): ByteArray? {
if(inputStream == null)
return null
val byteBuff = ByteArrayOutputStream()
val buffSize = inputStream.available()
val buff = ByteArray(buffSize)
var len = 0
while (inputStream.read(buff).also({ len = it }) != -1) {
byteBuff.write(buff, 0, len)
}
return byteBuff.toByteArray()
}
Thanks a lot again for your help and quick response.Kindly share your suggestion on above step. Also if anyone want to whole solution please let me know I will try to share