mirror of
				https://github.com/pierre42100/ComunicAndroid
				synced 2025-10-30 17:14:43 +00:00 
			
		
		
		
	Can post files without having to base64 them.
This commit is contained in:
		| @@ -5,6 +5,9 @@ import android.net.ConnectivityManager; | ||||
| import android.net.NetworkInfo; | ||||
|  | ||||
| import org.communiquons.android.comunic.client.BuildConfig; | ||||
| import org.communiquons.android.comunic.client.data.models.APIFileRequest; | ||||
| import org.communiquons.android.comunic.client.data.models.APIPostData; | ||||
| import org.communiquons.android.comunic.client.data.models.APIPostFile; | ||||
| import org.communiquons.android.comunic.client.data.models.APIRequest; | ||||
| import org.communiquons.android.comunic.client.data.models.APIResponse; | ||||
|  | ||||
| @@ -16,8 +19,11 @@ import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.io.OutputStream; | ||||
| import java.io.OutputStreamWriter; | ||||
| import java.io.PrintWriter; | ||||
| import java.net.HttpURLConnection; | ||||
| import java.net.MalformedURLException; | ||||
| import java.net.URL; | ||||
| import java.net.URLConnection; | ||||
| import java.util.ArrayList; | ||||
|  | ||||
| /** | ||||
| @@ -115,6 +121,126 @@ public class APIRequestHelper { | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute an API request over the server | ||||
|      * | ||||
|      * Note : this methods is based on a StackOverflow answer: | ||||
|      * https://stackoverflow.com/a/33149413/3781411 | ||||
|      * | ||||
|      * @param req Information about the request | ||||
|      * @return The response of the server | ||||
|      * @throws Exception In case of failure during the connection with the API | ||||
|      */ | ||||
|     public APIResponse execPostFile(APIFileRequest req) throws Exception { | ||||
|  | ||||
|         //Add API and login tokens to the request | ||||
|         addAPItokens(req); | ||||
|         addLoginTokens(req); | ||||
|  | ||||
|         //Prepare response | ||||
|         APIResponse response = new APIResponse(); | ||||
|         HttpURLConnection conn = null; | ||||
|         OutputStream out; | ||||
|         PrintWriter writer; | ||||
|  | ||||
|         //Create unique boundary | ||||
|         String boundary = "===" + System.currentTimeMillis() + "==="; | ||||
|         String LINE_FEED = "\r\n"; | ||||
|  | ||||
|         try { | ||||
|  | ||||
|             //Initialize connection | ||||
|             URL url = new URL(BuildConfig.api_url + req.getRequest_uri()); | ||||
|             conn = (HttpURLConnection) url.openConnection(); | ||||
|             conn.setUseCaches(false); | ||||
|             conn.setDoInput(true); | ||||
|             conn.setDoOutput(true); | ||||
|             conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); | ||||
|  | ||||
|             //Get output stream | ||||
|             out = conn.getOutputStream(); | ||||
|             writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8")); | ||||
|  | ||||
|             //Append values | ||||
|             for(APIPostData value : req.getParameters()){ | ||||
|  | ||||
|                 writer.append("--" + boundary).append(LINE_FEED); | ||||
|                 writer.append("Content-Disposition: form-data; name=\"" + value.getEncodedKeyName() + "\"") | ||||
|                         .append(LINE_FEED); | ||||
|                 writer.append("Content-Type: form-data; charset=UTF-8").append( | ||||
|                         LINE_FEED); | ||||
|                 writer.append(LINE_FEED); | ||||
|                 writer.append(value.getKey_value()).append(LINE_FEED); | ||||
|                 writer.flush(); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             //Append files | ||||
|             for(APIPostFile file : req.getFiles()){ | ||||
|  | ||||
|                 String fileName = file.getFileName(); | ||||
|                 writer.append("--" + boundary).append(LINE_FEED); | ||||
|                 writer.append( | ||||
|                         "Content-Disposition: form-data; name=\"" + file.getFieldName() | ||||
|                                 + "\"; filename=\"" + fileName + "\"") | ||||
|                         .append(LINE_FEED); | ||||
|                 writer.append( | ||||
|                         "Content-Type: " | ||||
|                                 + URLConnection.guessContentTypeFromName(fileName)) | ||||
|                         .append(LINE_FEED); | ||||
|                 writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED); | ||||
|                 writer.append(LINE_FEED); | ||||
|                 writer.flush(); | ||||
|  | ||||
|                 out.write(file.getByteArray()); | ||||
|                 out.flush(); | ||||
|  | ||||
|                 writer.append(LINE_FEED); | ||||
|                 writer.flush(); | ||||
|             } | ||||
|  | ||||
|             //Finish request and get response | ||||
|             writer.append(LINE_FEED).flush(); | ||||
|             writer.append("--" + boundary + "--").append(LINE_FEED); | ||||
|             writer.close(); | ||||
|  | ||||
|             StringBuilder responseBuffer = new StringBuilder(); | ||||
|             BufferedReader reader = new BufferedReader(new InputStreamReader( | ||||
|                     conn.getInputStream())); | ||||
|             String line; | ||||
|             while ((line = reader.readLine()) != null) { | ||||
|                 responseBuffer.append(line); | ||||
|             } | ||||
|             reader.close(); | ||||
|             conn.disconnect(); | ||||
|  | ||||
|             //Return the response | ||||
|             response.setResponse_code(conn.getResponseCode()); | ||||
|             response.setResponse(responseBuffer.toString()); | ||||
|         } | ||||
|  | ||||
|         //Malformed URL Exceptions must be fixed by dev | ||||
|         catch (MalformedURLException e) { | ||||
|             e.printStackTrace(); | ||||
|             throw new RuntimeException("MalformedURLException should never occur..."); | ||||
|         } | ||||
|  | ||||
|         catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|             response.setResponse_code(0); | ||||
|  | ||||
|             if(req.isTryContinueOnError() && conn != null){ | ||||
|                 response.setResponse_code(conn.getResponseCode()); | ||||
|                 return response; | ||||
|             } | ||||
|  | ||||
|             //Throw an exception | ||||
|             throw new Exception("Could not connect to the server"); | ||||
|         } | ||||
|  | ||||
|         return response; | ||||
|     } | ||||
|  | ||||
|     // Reads an InputStream and converts it to a String. | ||||
|     private String readIt(InputStream stream) throws IOException { | ||||
|  | ||||
| @@ -133,7 +259,7 @@ public class APIRequestHelper { | ||||
|     /** | ||||
|      * Add the API client tokens to API request object | ||||
|      * | ||||
|      * @param params The request parametres to update | ||||
|      * @param params The request parameters to update | ||||
|      */ | ||||
|     private void addAPItokens(APIRequest params){ | ||||
|         params.addString("serviceName", BuildConfig.api_service_name); | ||||
|   | ||||
| @@ -1,9 +1,13 @@ | ||||
| package org.communiquons.android.comunic.client.data.helpers; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.graphics.Bitmap; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.util.Log; | ||||
|  | ||||
| import org.communiquons.android.comunic.client.data.models.APIFileRequest; | ||||
| import org.communiquons.android.comunic.client.data.models.APIPostFile; | ||||
| import org.communiquons.android.comunic.client.data.models.APIRequest; | ||||
| import org.communiquons.android.comunic.client.data.models.APIResponse; | ||||
| import org.communiquons.android.comunic.client.data.models.ConversationMessage; | ||||
| @@ -82,23 +86,36 @@ public class ConversationMessagesHelper { | ||||
|      * | ||||
|      * @param convID Target conversation ID | ||||
|      * @param message The message to send | ||||
|      * @param image Base64 encoded image to include with the message (can be null) | ||||
|      * @param image Image to include with the request, as bitmap (can be null) | ||||
|      * @return true in case of success / false else | ||||
|      */ | ||||
|     public boolean sendMessage(int convID, String message, @Nullable String image){ | ||||
|     public boolean sendMessage(int convID, String message, @Nullable Bitmap image){ | ||||
|  | ||||
|         //Make an API request | ||||
|         APIRequest params = new APIRequest(mContext, | ||||
|         APIFileRequest params = new APIFileRequest(mContext, | ||||
|                 "conversations/sendMessage"); | ||||
|         params.addString("conversationID", ""+convID); | ||||
|         params.addString("message", message); | ||||
|  | ||||
|         //Include image (if any) | ||||
|         if(image != null) | ||||
|             params.addString("image", "data:image/png;base64," + image); | ||||
|         if(image != null) { | ||||
|             APIPostFile file = new APIPostFile(); | ||||
|             file.setFieldName("image"); | ||||
|             file.setFileName("conversationImage.png"); | ||||
|             file.setBitmap(image); | ||||
|             params.addFile(file); | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|             new APIRequestHelper().exec(params); | ||||
|  | ||||
|             if(image != null){ | ||||
|                 //Perform a POST request | ||||
|                 new APIRequestHelper().execPostFile(params); | ||||
|             } | ||||
|             else | ||||
|                 //Perform normal request | ||||
|                 new APIRequestHelper().exec(params); | ||||
|  | ||||
|             return true; | ||||
|         } catch (Exception e){ | ||||
|             e.printStackTrace(); | ||||
|   | ||||
| @@ -0,0 +1,51 @@ | ||||
| package org.communiquons.android.comunic.client.data.models; | ||||
|  | ||||
| import android.content.Context; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
|  | ||||
| /** | ||||
|  * This class handles information about the request that includes files to the server | ||||
|  * | ||||
|  * @author Pierre HUBERT | ||||
|  * Created by pierre on 4/21/18. | ||||
|  */ | ||||
|  | ||||
| public class APIFileRequest extends APIRequest { | ||||
|  | ||||
|     /** | ||||
|      * The list of post files | ||||
|      */ | ||||
|     private ArrayList<APIPostFile> files; | ||||
|  | ||||
|     /** | ||||
|      * The class constructor | ||||
|      * | ||||
|      * @param context The context of the request | ||||
|      * @param uri     The request URI on the server | ||||
|      */ | ||||
|     public APIFileRequest(Context context, String uri) { | ||||
|         super(context, uri); | ||||
|  | ||||
|         //Create files list | ||||
|         files = new ArrayList<>(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Add a file to the request | ||||
|      * | ||||
|      * @param file The file to add | ||||
|      */ | ||||
|     public void addFile(APIPostFile file){ | ||||
|         files.add(file); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the list of files | ||||
|      * | ||||
|      * @return The list of the files to include into the request | ||||
|      */ | ||||
|     public ArrayList<APIPostFile> getFiles() { | ||||
|         return files; | ||||
|     } | ||||
| } | ||||
| @@ -9,7 +9,7 @@ import java.net.URLEncoder; | ||||
|  * Created by pierre on 10/31/17. | ||||
|  */ | ||||
|  | ||||
| class APIPostData { | ||||
| public class APIPostData { | ||||
|  | ||||
|     /** | ||||
|      * The name of the key | ||||
| @@ -32,6 +32,52 @@ class APIPostData { | ||||
|         key_value = value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the name of the key | ||||
|      * | ||||
|      * @return The name of key | ||||
|      */ | ||||
|     public String getKey_name() { | ||||
|         return key_name; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the value associated with the ky | ||||
|      * | ||||
|      * @return The value of the key | ||||
|      */ | ||||
|     public String getKey_value() { | ||||
|         return key_value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the key name, as an encoded string | ||||
|      * | ||||
|      * @return The encoded key name | ||||
|      */ | ||||
|     public String getEncodedKeyName(){ | ||||
|         try { | ||||
|             return URLEncoder.encode(getKey_name(), "UTF-8"); | ||||
|         } catch (java.io.UnsupportedEncodingException e){ | ||||
|             e.printStackTrace(); | ||||
|             throw new RuntimeException("Unsupported encoding : UTF-8 !", e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the key value, as an encoded string | ||||
|      * | ||||
|      * @return The encoded key value | ||||
|      */ | ||||
|     public String getEncodedKeyValue(){ | ||||
|         try { | ||||
|             return URLEncoder.encode(getKey_value(), "UTF-8"); | ||||
|         } catch (java.io.UnsupportedEncodingException e){ | ||||
|             e.printStackTrace(); | ||||
|             throw new RuntimeException("Unsupported encoding : UTF-8 !", e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the the name and the value of the key in an encoded form | ||||
|      * | ||||
|   | ||||
| @@ -0,0 +1,61 @@ | ||||
| package org.communiquons.android.comunic.client.data.models; | ||||
|  | ||||
| import android.graphics.Bitmap; | ||||
| import android.support.annotation.NonNull; | ||||
|  | ||||
| import java.io.ByteArrayOutputStream; | ||||
|  | ||||
| /** | ||||
|  * Single file information included in a request to the API | ||||
|  * | ||||
|  * @author Pierre HUBERT | ||||
|  * Created by pierre on 4/21/18. | ||||
|  */ | ||||
|  | ||||
| public class APIPostFile { | ||||
|  | ||||
|     //Private fields | ||||
|     private String fieldName; | ||||
|     private String fileName; | ||||
|     private byte[] byteArray; | ||||
|  | ||||
|  | ||||
|     //Set and get field name | ||||
|     public void setFieldName(String fieldName) { | ||||
|         this.fieldName = fieldName; | ||||
|     } | ||||
|  | ||||
|     public String getFieldName() { | ||||
|         return fieldName; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     //Set and get file name | ||||
|     public void setFileName(String fileName) { | ||||
|         this.fileName = fileName; | ||||
|     } | ||||
|  | ||||
|     public String getFileName() { | ||||
|         return fileName; | ||||
|     } | ||||
|  | ||||
|     //Set and get byte array | ||||
|     public void setByteArray(byte[] byteArray) { | ||||
|         this.byteArray = byteArray; | ||||
|     } | ||||
|  | ||||
|     public byte[] getByteArray() { | ||||
|         return byteArray; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set a bitmap as the file | ||||
|      * | ||||
|      * @param bmp Bitmap to set | ||||
|      */ | ||||
|     public void setBitmap(@NonNull Bitmap bmp){ | ||||
|         ByteArrayOutputStream stream = new ByteArrayOutputStream(); | ||||
|         bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); | ||||
|         setByteArray(stream.toByteArray()); | ||||
|     } | ||||
| } | ||||
| @@ -112,6 +112,15 @@ public class APIRequest { | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the list of parameters | ||||
|      * | ||||
|      * @return The list of parameters | ||||
|      */ | ||||
|     public ArrayList<APIPostData> getParameters() { | ||||
|         return parameters; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the context of the request | ||||
|      * | ||||
|   | ||||
| @@ -535,14 +535,8 @@ public class ConversationFragment extends Fragment | ||||
|  | ||||
|             @Override | ||||
|             protected Boolean doInBackground(Void... params) { | ||||
|                 String message_image = null; | ||||
|  | ||||
|                 //Reduce Bitmap and convert it to a base64-encoded string | ||||
|                 if(new_message_bitmap != null) | ||||
|                         message_image = BitmapUtils.bitmapToBase64( | ||||
|                                 BitmapUtils.reduceBitmap(new_message_bitmap, 1199, 1199)); | ||||
|  | ||||
|                 return convMessHelper.sendMessage(conversation_id, message_content, message_image); | ||||
|                 return convMessHelper.sendMessage(conversation_id, | ||||
|                         message_content, new_message_bitmap); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Pierre
					Pierre