Issue with image upload using Retrofit - retrofit2

I'm using retrofit to upload images on server, image are uploading successfully, but without extension.
Means only image name is uploading to database, extension is not there.
So image became useless for me.
please provide help.
here is my method in interface->
#FormUrlEncoded
#POST("/webservices/AssessorAssetsUpload.php")
Call<ImageModel> uploadImage(
#Field("name")String pictype,
#Field("type")String uploadtype,
#Field("accesser_id")String asses_id,
#Field("paper_schedule_id")String paper_id,
#Field("imagefile")String image
);
my activity code->
String image=imagetoString();
RetrofitInterface retrofit=ApiClient.getApiClient().create(RetrofitInterface.class);
Call<ImageModel> call=retrofit.uploadImage(imageName,"image",assessor_id,paperId,image);
call.enqueue(new Callback<ImageModel>() {
#Override
public void onResponse(Call<ImageModel> call, Response<ImageModel> response) {
System.out.println(response.body().getStatus()+" "+response.body().getMsg()+" "+response.body().getUrl());
}
#Override
public void onFailure(Call<ImageModel> call, Throwable t) {
t.printStackTrace();
}
});
}
private String imagetoString(){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte[] bytes=stream.toByteArray();
return Base64.encodeToString(bytes,Base64.DEFAULT);
}

We use Multipart instead of formurlencoded in case of any multimedia object.
#Multipart
#POST("/webservices/AssessorAssetsUpload.php")
Call<ImageModel> uploadImage(
#Part("name")RequestBody pictype,
#Part("type")RequestBody uploadtype,
#Part("accesser_id")RequestBody asses_id,
#Part("paper_schedule_id")RequestBody paper_id,
#Part("imagefile")MultipartBody.Part image
);
MultipartBody.Part image=imagetoPart();
RetrofitInterface retrofit=ApiClient.getApiClient().create(RetrofitInterface.class);
Call<ImageModel> call=retrofit.uploadImage(
getTextRequest("imageName"),
getTextRequest("image"),
getTextRequest("assessor_id"),
getTextRequest("paperId"),
image
);
call.enqueue(new Callback<ImageModel>() {
#Override
public void onResponse(Call<ImageModel> call, Response<ImageModel> response) {
System.out.println(response.body().getStatus()+" "+response.body().getMsg()+" "+response.body().getUrl());
}
#Override
public void onFailure(Call<ImageModel> call, Throwable t) {
t.printStackTrace();
}
});
}
private String imagetoPart(){
Bitmap bitmap = BitmapFactory.decodeFile("Image Path");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte[] bytes=stream.toByteArray();
RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), bytes);
MultipartBody.Part part = MultipartBody.Part.createFormData("name", "name", reqFile);
return part;
}
private RequestBody getTextRequest(String body) {
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), body);
return requestBody;
}
We need to convert the fields into request body and image into a multipart body to send it as a multipart request. This will do your work.

Related

How to use Firebase push notification using custom data like image

There is problem when sending the notification using firebase the notification in which the title and text is shown but when sending other data the String imgurl = remoteMessage.getData().get("image"); is on null reference how to solve this problem.
Here is my code
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
String title = remoteMessage.getData().get("title");
String body = remoteMessage.getData().get("body");
String imgurl = remoteMessage.getData().get("image");
bitmap = getbitmap(imgurl);
getnotifiacation(bitmap, title, body, imgurl);
}
#Override
public void onNewToken(String token) {
}
private void getnotifiacation(Bitmap bitmap, String title, String body, String imgurl) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
notifiaction = new NotificationCompat.Builder(this, id)
.setAutoCancel(true)
.setContentTitle(title)
.setContentText(body)
.setLargeIcon(getbitmap(imgurl))
.setSmallIcon(R.drawable.ic_launcher_background)
.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap))
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(id, "notifiaction",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0, notifiaction.build());
}
public static Bitmap getbitmap(String imgurl) {
try {
URL url = new URL(imgurl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
Thank you
I got the error.The error was in payload code here is the right code below
1 st
connect your app to firebase then after you have to implements the library for the firebase messaging service.
In Manifest
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
Create class FirebaseMessagingservice
public class FirebaseMessagingservice extends FirebaseMessagingService {
NotificationCompat.Builder notifiaction;
Bitmap bitmap;
String id="Default";
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage)
{
String title = remoteMessage.getData().get("title");
String body = remoteMessage.getData().get("body");
String imgurl = remoteMessage.getData().get("image");
//getting custom data from php
bitmap=getbitmap(imgurl);
getnotifiacation(bitmap,title,body,imgurl);
}
#Override
public void onNewToken(String token) {
}
private void getnotifiacation(Bitmap bitmap, String title, String body, String imgurl)
{
Intent intent=new Intent(this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_ONE_SHOT);
notifiaction=new NotificationCompat.Builder(this,id)
.setAutoCancel(true)
.setContentTitle(title)
.setContentText(body)
.setLargeIcon(getbitmap(imgurl))
.setSmallIcon(R.drawable.ic_launcher_background)
.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap))
.setContentIntent(pendingIntent);
NotificationManager notificationManager=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(id,"notifiaction",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0,notifiaction.build());
}
public static Bitmap getbitmap(String imgurl)
{
try
{
URL url=new URL(imgurl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream inputStream=connection.getInputStream();
Bitmap bitmap=BitmapFactory.decodeStream(inputStream);
return bitmap;
}catch (IOException e)
{
e.printStackTrace();
return null;
}
}// code for converting imgurl into bitmap
and here is the PHP code
php code link
When app is background the onMessageReceived is not work for this above payload code will work for you Thank you :)

Spring Boot GRPC: ServerIntereceptor to read data in the request, and set it in the response

There is a field called "metadata" (not to be confused with GRPC metadata) that is present in every request proto that comes to the GRPC service:
message MyRequest {
RequestResponseMetadata metadata = 1;
...
}
And the same field is also present in all responses:
message MyResponse {
RequestResponseMetadata metadata = 1;
...
}
I am trying to write a ServerInterceptor (or something else, if it works) to read the "metadata" field from the request, keep it somewhere, and then set it in the response once done processing the request.
Attempt 1: ThreadLocal
public class ServerInterceptor implements io.grpc.ServerInterceptor {
private ThreadLocal<RequestResponseMetadata> metadataThreadLocal = new ThreadLocal<>();
#Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call,
final Metadata requestHeaders,
ServerCallHandler<ReqT, RespT> next) {
return new SimpleForwardingServerCallListener<ReqT>(
next.startCall(
new SimpleForwardingServerCall<ReqT, RespT>(call) {
#Override
public void sendMessage(RespT message) {
super.sendMessage(
(RespT)
MetadataUtils.setMetadata(
(GeneratedMessageV3) message, metadataThreadLocal.get()));
metadataThreadLocal.remove();
}
},
requestHeaders)) {
#Override
public void onMessage(ReqT request) {
// todo nava see if ReqT can extend GenericV3Message
var metadata = MetadataUtils.getMetadata((GeneratedMessageV3) request);
metadataThreadLocal.set(metadata);
super.onMessage(request);
}
};
}
}
I tried to use ThreadLocal, to later realise that sendMessage and onMessage need not necessary to be on the same thread.
Attempt 2: GRPC Context
public class ServerInterceptor implements io.grpc.ServerInterceptor {
public static final Context.Key<RequestResponseMetadata> METADATA_KEY = Context.key("metadata");
#Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call,
final Metadata requestHeaders,
ServerCallHandler<ReqT, RespT> next) {
return new SimpleForwardingServerCallListener<ReqT>(
next.startCall(
new SimpleForwardingServerCall<ReqT, RespT>(call) {
#Override
public void sendMessage(RespT message) {
super.sendMessage(
(RespT)
MetadataUtils.setMetadata(
(GeneratedMessageV3) message, METADATA_KEY.get()));
}
},
requestHeaders)) {
#Override
public void onMessage(ReqT request) {
var metadata = MetadataUtils.getMetadata((GeneratedMessageV3) request);
var newContext = Context.current().withValue(METADATA_KEY, metadata);
oldContext = newContext.attach();
super.onMessage(request);
}
};
}
}
I am planning to detach the context in a onComplete(), but before it reaches there itself, METADATA_KEY.get() in sendMessage returns null, while I was expecting it to return the data.
Even before hitting the sendMessage() function, I get this in the console, indicating that I am doing something wrong:
3289640 [grpc-default-executor-0] ERROR i.g.ThreadLocalContextStorage - Context was not attached when detaching
java.lang.Throwable: null
at io.grpc.ThreadLocalContextStorage.detach(ThreadLocalContextStorage.java:48)
at io.grpc.Context.detach(Context.java:421)
at io.grpc.Context$CancellableContext.detach(Context.java:761)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:39)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
How do I read data when a request is received, store it somewhere and use it when the response is send back?
You can use Metadata to pass values from the request to the response:
public class MetadataServerInterceptor implements ServerInterceptor {
public static final Metadata.Key<byte[]> METADATA_KEY = Metadata.Key.of("metadata-bin", Metadata.BINARY_BYTE_MARSHALLER);
#Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
var serverCall = new ForwardingServerCall.SimpleForwardingServerCall<>(call) {
#Override
public void sendMessage(RespT message) {
byte[] metadata = headers.get(METADATA_KEY);
message = (RespT) MetadataUtils.setMetadata((GeneratedMessageV3) message, metadata);
super.sendMessage(message);
}
};
ServerCall.Listener<ReqT> listenerWithContext = Contexts.interceptCall(Context.current(), serverCall, headers, next);
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<>(listenerWithContext) {
#Override
public void onMessage(ReqT message) {
byte[] metadata = MetadataUtils.getMetadata((GeneratedMessageV3) message);
headers.put(METADATA_KEY, metadata);
super.onMessage(message);
}
};
}
}
Note: Since it is not possible to put the instance of RequestResponseMetadata in the metadata (at least without implementing a custom marshaller), you can save it there as a byte array. You can use toByteArray() on your RequestResponseMetadata object to get byte[] and RequestResponseMetadata.#parseFrom(byte[]) to get the object from byte[].

AWS Gzip compression not working in java for isBase64Encoded

I have been working on Gzipping the response, but its work's fine in nodejs, but the same code is not working in java platform. After digging further i found that the key isBase64Encoded : true is not correctly been identified in the client( Chrome browser specifically)
public class ExampleHandler1 implements RequestHandler<AwsProxyRequest,AwsProxyResponse> {
#Override
public AwsProxyResponse handleRequest(AwsProxyRequest input, Context context) {
AwsProxyResponse response = new AwsProxyResponse(200, Collections.singletonMap("X-Powered-By", "AWS Lambda & serverless"), "Aaytu");
try {
HashMap<String, String> headermap = new HashMap<>();
headermap.put("Content-Encoding", "gzip");
headermap.put("Content-Type", "text/html");
String responseString = Base64.getMimeEncoder().encodeToString(GzipCompressor.compress("Hello there..!!!").getBytes());
AwsProxyResponse retVal = new AwsProxyResponse(200, headermap, responseString);
retVal.setBase64Encoded(true);
return retVal;
} catch (Exception e) {
}
return response;
}
}

RestTemplate postForObject response getting truncated

Trying to fetch the response using spring web client, but the result response is getting truncated as the response size is more than that of string class. Is there any other way to get the response without being truncated?
LinkedMultiValueMap<String, Object> requestMap = new LinkedMultiValueMap<String, Object>();
//String response = "";
try{
File tempFile = File.createTempFile("ccda", "File");
FileOutputStream out = new FileOutputStream(tempFile);
IOUtils.copy(ccdaFile.getInputStream(), out);
requestMap.add("ccdaFile", new FileSystemResource(tempFile));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity =
new HttpEntity<LinkedMultiValueMap<String, Object>>(requestMap, headers);
RestTemplate restTemplate = new RestTemplate();
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
formConverter.setCharset(Charset.forName("UTF8"));
restTemplate.getMessageConverters().add(formConverter);
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
String response = restTemplate.postForObject("localhost:8080",
requestEntity, String.class);
tempFile.delete();
}catch(Exception exc)
{
exc.printStackTrace();
}
You may use an InputStream
I think you may do in this way:
InputStream is = rt.execute("localhost:8080", HttpMethod.POST, requestCallback, responseExtractor);
Where requestCallback is an implementation of org.springframework.web.client.RequestCallback like this one
public class MyRequestCallback implements RequestCallback
{
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException
{
request.getHeaders().add(HttpHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE);
request.getHeaders().add(HttpHeaders.ACCEPT, MimeTypeUtils.APPLICATION_JSON_VALUE);
}
}
While responseExtractor may by an instance of this class
public class MyResponseExtractor implements ResponseExtractor<InputStream>
{
#Override
public Boolean extractData(ClientHttpResponse response) throws IOException
{
HttpStatus status = response.getStatusCode();
switch (status)
{
case OK:
return response.getBody();
default:
return null;
}
}
}
Once obtained the InputStream you can manage it
Hope it is usefull

How to use async servlet + non blocking IO for file download?

My image files are stored in database (I know they shouldn't be, but can't help).
To be able to render them on clients, I've implemented an async servlet that helps read the binary stream off the database column and write on to the Output Stream of Servlet Response. Traditional IO works just fine here.
When I thought of trying the non blocking IO with async servlet (to test performance), my binary data returned in the response keeps getting corrupted.
Starting with the Oracle Blog, I've seen various examples of file upload with async NIO servlet, but no help with my issue.
Here's the servlet code:
#WebServlet(asyncSupported = true, urlPatterns = "/myDownloadServlet")
public class FileRetrievalServletAsyncNIO extends HttpServlet
{
private static final long serialVersionUID = -6914766655133758332L;
#Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Queue<byte[]> containerQueue = new LinkedList<byte[]>();
AsyncContext asyncContext = request.startAsync();
asyncContext.addListener(new AsyncListenerImpl());
asyncContext.setTimeout(120000);
try
{
long attachmentId = Long.valueOf(request.getParameter("id"));
MyAttachmentDataObject retObj = ServletUtils.fetchAttachmentHeaders(attachmentId);
response = (HttpServletResponse) asyncContext.getResponse();
response.setHeader("Content-Length", String.valueOf(retObj.getContentLength()));
if (Boolean.valueOf(request.getParameter(ServletConstants.REQ_PARAM_ENABLE_DOWNLOAD)))
response.setHeader("Content-disposition", "attachment; filename=" + retObj.getName());
response.setContentType(retObj.getContentType());
ServletOutputStream sos = response.getOutputStream();
ServletUtils.fetchContentStreamInChunks(attachmentId, containerQueue); // reads from database and adds to the queue in chunks
sos.setWriteListener(new WriteListenerImpl(sos, containerQueue, asyncContext));
}
catch (NumberFormatException | IOException exc)
{
exc.printStackTrace();
request.setAttribute("message", "Failed");
}
}
}
Here's the write listener implementation
public class WriteListenerImpl implements WriteListener
{
private ServletOutputStream output = null;
private Queue<byte[]> queue = null;
private AsyncContext asyncContext = null;
private HttpServletRequest request = null;
private HttpServletResponse response = null;
public WriteListenerImpl(ServletOutputStream sos, Queue<byte[]> q, AsyncContext aCtx)
{
output = sos;
queue = q;
asyncContext = aCtx;
request = (HttpServletRequest) asyncContext.getRequest();
}
#Override
public void onWritePossible() throws IOException
{
while(output.isReady())
{
while (!queue.isEmpty())
{
byte[] temp = queue.poll();
output.write(temp, 0, temp.length);
}
asyncContext.complete();
request.setAttribute("message", "Success");
}
}
#Override
public void onError(Throwable t)
{
System.err.println(t);
try
{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
catch (IOException exc)
{
exc.printStackTrace();
}
request.setAttribute("message", "Failure");
asyncContext.complete();
}
}
The response data looks like this:
What am I doing wrong?
Not sure exactly what you expect the output to look like but in terms of async i/o you should check output.isReady() before every write. So your onWritePossible code should be:
while(output.isReady() && !queue.isEmpty())
{
byte[] temp = queue.poll();
output.write(temp, 0, temp.length);
}
if (queue.isEmpty()) {
asyncContext.complete();
request.setAttribute("message", "Success");
}
This allows onWritePossible() to return if writing becomes blocked which is the basically the point of async I/O.
If you write when writing is blocked (output.isReady() would return false) different implementations may either ignore the write or throw an exception. Either way your output data would be either missing some writes in the middle or truncated.

Resources