Enviar archivos usando POST con HttpURLConnection

Dado que los desarrolladores de Android recomiendan utilizar la clase HttpURLConnection , me preguntaba si alguien me puede dar un buen ejemplo sobre cómo enviar un “archivo” de bitmap (en realidad una secuencia en memoria) a través de POST a un servidor Apache HTTP. No me interesan las cookies o la autenticación ni nada complicado, pero solo quiero tener una implementación lógica y confiable. Todos los ejemplos que he visto por aquí se parecen más a “probemos esto y quizás funcione”.

En este momento, tengo este código:

 URL url; HttpURLConnection urlConnection = null; try { url = new URL("http://example.com/server.cgi"); urlConnection = (HttpURLConnection) url.openConnection(); } catch (Exception e) { this.showDialog(getApplicationContext(), e.getMessage()); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } 

donde showDialog solo debería mostrar un AlertDialog (en caso de una URL no válida?).

Ahora, digamos que genero un bitmap como ese: Bitmap image = this.getBitmap() dentro de un control derivado de View y quiero enviarlo a través de POST. ¿Cuál sería el procedimiento adecuado para lograr tal cosa? ¿Qué clases necesito usar? ¿Puedo usar HttpPost como en este ejemplo ? Si es así, ¿cómo construiría InputStreamEntity para mi bitmap? Me parece repugnante que se requiera primero almacenar el bitmap en un archivo en el dispositivo.


También debo mencionar que realmente necesito enviar todos los píxeles inalterados del bitmap original al servidor, por lo que no puedo convertirlo a JPEG.

No tengo idea de por qué la clase HttpURLConnection no proporciona ningún medio para enviar archivos sin tener que componer el contenedor de archivos manualmente. Esto es lo que terminé haciendo, pero si alguien conoce una solución mejor, hágamelo saber.

Datos de entrada:

 Bitmap bitmap = myView.getBitmap(); 

Cosas estáticas:

 String attachmentName = "bitmap"; String attachmentFileName = "bitmap.bmp"; String crlf = "\r\n"; String twoHyphens = "--"; String boundary = "*****"; 

Configure la solicitud:

 HttpURLConnection httpUrlConnection = null; URL url = new URL("http://example.com/server.cgi"); httpUrlConnection = (HttpURLConnection) url.openConnection(); httpUrlConnection.setUseCaches(false); httpUrlConnection.setDoOutput(true); httpUrlConnection.setRequestMethod("POST"); httpUrlConnection.setRequestProperty("Connection", "Keep-Alive"); httpUrlConnection.setRequestProperty("Cache-Control", "no-cache"); httpUrlConnection.setRequestProperty( "Content-Type", "multipart/form-data;boundary=" + this.boundary); 

Inicie el contenedor de contenido:

 DataOutputStream request = new DataOutputStream( httpUrlConnection.getOutputStream()); request.writeBytes(this.twoHyphens + this.boundary + this.crlf); request.writeBytes("Content-Disposition: form-data; name=\"" + this.attachmentName + "\";filename=\"" + this.attachmentFileName + "\"" + this.crlf); request.writeBytes(this.crlf); 

Convertir Bitmap de Bitmap a ByteBuffer :

 //I want to send only 8 bit black & white bitmaps byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight()]; for (int i = 0; i < bitmap.getWidth(); ++i) { for (int j = 0; j < bitmap.getHeight(); ++j) { //we're interested only in the MSB of the first byte, //since the other 3 bytes are identical for B&W images pixels[i + j] = (byte) ((bitmap.getPixel(i, j) & 0x80) >> 7); } } request.write(pixels); 

Contenedor de contenido final:

 request.writeBytes(this.crlf); request.writeBytes(this.twoHyphens + this.boundary + this.twoHyphens + this.crlf); 

Tampón de salida de descarga:

 request.flush(); request.close(); 

Obtener una respuesta:

 InputStream responseStream = new BufferedInputStream(httpUrlConnection.getInputStream()); BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream)); String line = ""; StringBuilder stringBuilder = new StringBuilder(); while ((line = responseStreamReader.readLine()) != null) { stringBuilder.append(line).append("\n"); } responseStreamReader.close(); String response = stringBuilder.toString(); 

Cerrar flujo de respuesta:

 responseStream.close(); 

Cierre la conexión:

 httpUrlConnection.disconnect(); 

PD: Por supuesto que tuve que ajustar la solicitud en private class AsyncUploadBitmaps extends AsyncTask , para hacer que la plataforma Android sea feliz, porque no le gusta tener solicitudes de red en el hilo principal.

De hecho, encontré una mejor manera de enviar archivos usando HttpURLConnection usando MultipartEntity

 private static String multipost(String urlString, MultipartEntity reqEntity) { try { URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(10000); conn.setConnectTimeout(15000); conn.setRequestMethod("POST"); conn.setUseCaches(false); conn.setDoInput(true); conn.setDoOutput(true); conn.setRequestProperty("Connection", "Keep-Alive"); conn.addRequestProperty("Content-length", reqEntity.getContentLength()+""); conn.addRequestProperty(reqEntity.getContentType().getName(), reqEntity.getContentType().getValue()); OutputStream os = conn.getOutputStream(); reqEntity.writeTo(conn.getOutputStream()); os.close(); conn.connect(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { return readStream(conn.getInputStream()); } } catch (Exception e) { Log.e(TAG, "multipart post error " + e + "(" + urlString + ")"); } return null; } private static String readStream(InputStream in) { BufferedReader reader = null; StringBuilder builder = new StringBuilder(); try { reader = new BufferedReader(new InputStreamReader(in)); String line = ""; while ((line = reader.readLine()) != null) { builder.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return builder.toString(); } 

Suponiendo que está cargando una imagen con datos de bitmap:

  Bitmap bitmap = ...; String filename = "filename.png"; ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos); ContentBody contentPart = new ByteArrayBody(bos.toByteArray(), filename); MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); reqEntity.addPart("picture", contentPart); String response = multipost("http://server.com", reqEntity); 

¡Y voilá! Sus datos de publicación contendrán un campo de imagen junto con el nombre de archivo y la ruta en su servidor.

Para cargar archivos en el servidor con algún parámetro usando MultipartUtility de manera simple.

MultipartUtility.java

 public class MultipartUtility { private final String boundary; private static final String LINE_FEED = "\r\n"; private HttpURLConnection httpConn; private String charset; private OutputStream outputStream; private PrintWriter writer; /** * This constructor initializes a new HTTP POST request with content type * is set to multipart/form-data * * @param requestURL * @param charset * @throws IOException */ public MultipartUtility(String requestURL, String charset) throws IOException { this.charset = charset; // creates a unique boundary based on time stamp boundary = "===" + System.currentTimeMillis() + "==="; URL url = new URL(requestURL); Log.e("URL", "URL : " + requestURL.toString()); httpConn = (HttpURLConnection) url.openConnection(); httpConn.setUseCaches(false); httpConn.setDoOutput(true); // indicates POST method httpConn.setDoInput(true); httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); httpConn.setRequestProperty("User-Agent", "CodeJava Agent"); httpConn.setRequestProperty("Test", "Bonjour"); outputStream = httpConn.getOutputStream(); writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true); } /** * Adds a form field to the request * * @param name field name * @param value field value */ public void addFormField(String name, String value) { writer.append("--" + boundary).append(LINE_FEED); writer.append("Content-Disposition: form-data; name=\"" + name + "\"") .append(LINE_FEED); writer.append("Content-Type: text/plain; charset=" + charset).append( LINE_FEED); writer.append(LINE_FEED); writer.append(value).append(LINE_FEED); writer.flush(); } /** * Adds a upload file section to the request * * @param fieldName name attribute in  * @param uploadFile a File to be uploaded * @throws IOException */ public void addFilePart(String fieldName, File uploadFile) throws IOException { String fileName = uploadFile.getName(); writer.append("--" + boundary).append(LINE_FEED); writer.append( "Content-Disposition: form-data; name=\"" + fieldName + "\"; 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(); FileInputStream inputStream = new FileInputStream(uploadFile); byte[] buffer = new byte[4096]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.flush(); inputStream.close(); writer.append(LINE_FEED); writer.flush(); } /** * Adds a header field to the request. * * @param name - name of the header field * @param value - value of the header field */ public void addHeaderField(String name, String value) { writer.append(name + ": " + value).append(LINE_FEED); writer.flush(); } /** * Completes the request and receives response from the server. * * @return a list of Strings as response in case the server returned * status OK, otherwise an exception is thrown. * @throws IOException */ public String finish() throws IOException { StringBuffer response = new StringBuffer(); writer.append(LINE_FEED).flush(); writer.append("--" + boundary + "--").append(LINE_FEED); writer.close(); // checks server's status code first int status = httpConn.getResponseCode(); if (status == HttpURLConnection.HTTP_OK) { BufferedReader reader = new BufferedReader(new InputStreamReader( httpConn.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); httpConn.disconnect(); } else { throw new IOException("Server returned non-OK status: " + status); } return response.toString(); } } 

Para upload tu file junto con los parámetros.

NOTA: ponga este código debajo en thread no-ui para obtener respuesta.

 String charset = "UTF-8"; String requestURL = "YOUR_URL"; MultipartUtility multipart = new MultipartUtility(requestURL, charset); multipart.addFormField("param_name_1", "param_value"); multipart.addFormField("param_name_2", "param_value"); multipart.addFormField("param_name_3", "param_value"); multipart.addFilePart("file_param_1", new File(file_path)); String response = multipart.finish(); // response from server. 

La solución de Jaydipsinh Zala no funcionó para mí, pero no sé por qué porque parece demasiado cerca de la solución.

Así que fusiono este con la gran solución y explicación de Mihai Todor y ahora esta clase funciona para mí. Si ayuda a alguien:

MultipartUtility2V.java

 import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; public class MultipartUtilityV2 { private HttpURLConnection httpConn; private DataOutputStream request; private final String boundary = "*****"; private final String crlf = "\r\n"; private final String twoHyphens = "--"; /** * This constructor initializes a new HTTP POST request with content type * is set to multipart/form-data * * @param requestURL * @throws IOException */ public MultipartUtilityV2(String requestURL) throws IOException { // creates a unique boundary based on time stamp URL url = new URL(requestURL); httpConn = (HttpURLConnection) url.openConnection(); httpConn.setUseCaches(false); httpConn.setDoOutput(true); // indicates POST method httpConn.setDoInput(true); httpConn.setRequestMethod("POST"); httpConn.setRequestProperty("Connection", "Keep-Alive"); httpConn.setRequestProperty("Cache-Control", "no-cache"); httpConn.setRequestProperty( "Content-Type", "multipart/form-data;boundary=" + this.boundary); request = new DataOutputStream(httpConn.getOutputStream()); } /** * Adds a form field to the request * * @param name field name * @param value field value */ public void addFormField(String name, String value)throws IOException { request.writeBytes(this.twoHyphens + this.boundary + this.crlf); request.writeBytes("Content-Disposition: form-data; name=\"" + name + "\""+ this.crlf); request.writeBytes("Content-Type: text/plain; charset=UTF-8" + this.crlf); request.writeBytes(this.crlf); request.writeBytes(value+ this.crlf); request.flush(); } /** * Adds a upload file section to the request * * @param fieldName name attribute in  * @param uploadFile a File to be uploaded * @throws IOException */ public void addFilePart(String fieldName, File uploadFile) throws IOException { String fileName = uploadFile.getName(); request.writeBytes(this.twoHyphens + this.boundary + this.crlf); request.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\";filename=\"" + fileName + "\"" + this.crlf); request.writeBytes(this.crlf); byte[] bytes = Files.readAllBytes(uploadFile.toPath()); request.write(bytes); } /** * Completes the request and receives response from the server. * * @return a list of Strings as response in case the server returned * status OK, otherwise an exception is thrown. * @throws IOException */ public String finish() throws IOException { String response =""; request.writeBytes(this.crlf); request.writeBytes(this.twoHyphens + this.boundary + this.twoHyphens + this.crlf); request.flush(); request.close(); // checks server's status code first int status = httpConn.getResponseCode(); if (status == HttpURLConnection.HTTP_OK) { InputStream responseStream = new BufferedInputStream(httpConn.getInputStream()); BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream)); String line = ""; StringBuilder stringBuilder = new StringBuilder(); while ((line = responseStreamReader.readLine()) != null) { stringBuilder.append(line).append("\n"); } responseStreamReader.close(); response = stringBuilder.toString(); httpConn.disconnect(); } else { throw new IOException("Server returned non-OK status: " + status); } return response; } } 

basado en la solución de Mihai, si alguien tiene el problema de guardar imágenes en el servidor como lo que sucedió en mi servidor. cambie la parte Bitmap totebuffer a:

 ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG,100,bos); byte[] pixels = bos.toByteArray(); 

No he probado esto, pero puede intentar usar PipedInputStream y PipedOutputStream. Puede ser algo así como:

 final Bitmap bmp = … // your bitmap // Set up Piped streams final PipedOutputStream pos = new PipedOutputStream(new ByteArrayOutputStream()); final PipedInputStream pis = new PipedInputStream(pos); // Send bitmap data to the PipedOutputStream in a separate thread new Thread() { public void run() { bmp.compress(Bitmap.CompressFormat.PNG, 100, pos); } }.start(); // Send POST request try { // Construct InputStreamEntity that feeds off of the PipedInputStream InputStreamEntity reqEntity = new InputStreamEntity(pis, -1); HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(url); reqEntity.setContentType("binary/octet-stream"); reqEntity.setChunked(true); httppost.setEntity(reqEntity); HttpResponse response = httpclient.execute(httppost); } catch (Exception e) { e.printStackTrace() } 

Esta respuesta https://stackoverflow.com/a/33149413/6481542 me llevó el 90% del camino con la carga de archivos de gran tamaño a un servidor Django de desarrollo, pero tuve que usar setFixedLengthStreamingMode para hacerlo funcionar. Eso requiere establecer la longitud del contenido antes de escribir el contenido, por lo que requiere una reescritura bastante significativa de la respuesta anterior. Aquí está mi resultado final

 public class MultipartLargeUtility { private final String boundary; private static final String LINE_FEED = "\r\n"; private HttpURLConnection httpConn; private String charset; private OutputStream outputStream; private PrintWriter writer; private final int maxBufferSize = 4096; private long contentLength = 0; private URL url; private List fields; private List files; private class FormField { public String name; public String value; public FormField(String name, String value) { this.name = name; this.value = value; } } private class FilePart { public String fieldName; public File uploadFile; public FilePart(String fieldName, File uploadFile) { this.fieldName = fieldName; this.uploadFile = uploadFile; } } /** * This constructor initializes a new HTTP POST request with content type * is set to multipart/form-data * * @param requestURL * @param charset * @throws IOException */ public MultipartLargeUtility(String requestURL, String charset, boolean requireCSRF) throws IOException { this.charset = charset; // creates a unique boundary based on time stamp boundary = "===" + System.currentTimeMillis() + "==="; url = new URL(requestURL); fields = new ArrayList<>(); files = new ArrayList<>(); if (requireCSRF) { getCSRF(); } } /** * Adds a form field to the request * * @param name field name * @param value field value */ public void addFormField(String name, String value) throws UnsupportedEncodingException { String fieldContent = "--" + boundary + LINE_FEED; fieldContent += "Content-Disposition: form-data; name=\"" + name + "\"" + LINE_FEED; fieldContent += "Content-Type: text/plain; charset=" + charset + LINE_FEED; fieldContent += LINE_FEED; fieldContent += value + LINE_FEED; contentLength += fieldContent.getBytes(charset).length; fields.add(new FormField(name, value)); } /** * Adds a upload file section to the request * * @param fieldName name attribute in  * @param uploadFile a File to be uploaded * @throws IOException */ public void addFilePart(String fieldName, File uploadFile) throws IOException { String fileName = uploadFile.getName(); String fieldContent = "--" + boundary + LINE_FEED; fieldContent += "Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"" + LINE_FEED; fieldContent += "Content-Type: " + URLConnection.guessContentTypeFromName(fileName) + LINE_FEED; fieldContent += "Content-Transfer-Encoding: binary" + LINE_FEED; fieldContent += LINE_FEED; // file content would go here fieldContent += LINE_FEED; contentLength += fieldContent.getBytes(charset).length; contentLength += uploadFile.length(); files.add(new FilePart(fieldName, uploadFile)); } /** * Adds a header field to the request. * * @param name - name of the header field * @param value - value of the header field */ //public void addHeaderField(String name, String value) { // writer.append(name + ": " + value).append(LINE_FEED); // writer.flush(); //} /** * Completes the request and receives response from the server. * * @return a list of Strings as response in case the server returned * status OK, otherwise an exception is thrown. * @throws IOException */ public List finish() throws IOException { List response = new ArrayList(); String content = "--" + boundary + "--" + LINE_FEED; contentLength += content.getBytes(charset).length; if (!openConnection()) { return response; } writeContent(); // checks server's status code first int status = httpConn.getResponseCode(); if (status == HttpURLConnection.HTTP_OK) { BufferedReader reader = new BufferedReader(new InputStreamReader( httpConn.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { response.add(line); } reader.close(); httpConn.disconnect(); } else { throw new IOException("Server returned non-OK status: " + status); } return response; } private boolean getCSRF() throws IOException { /// First, need to get CSRF token from server /// Use GET request to get the token CookieManager cookieManager = new CookieManager(); CookieHandler.setDefault(cookieManager); HttpURLConnection conn = null; conn = (HttpURLConnection) url.openConnection(); conn.setUseCaches(false); // Don't use a Cached Copy conn.setRequestMethod("GET"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.getContent(); conn.disconnect(); /// parse the returned object for the CSRF token CookieStore cookieJar = cookieManager.getCookieStore(); List cookies = cookieJar.getCookies(); String csrf = null; for (HttpCookie cookie : cookies) { Log.d("cookie", "" + cookie); if (cookie.getName().equals("csrftoken")) { csrf = cookie.getValue(); break; } } if (csrf == null) { Log.d(TAG, "Unable to get CSRF"); return false; } Log.d(TAG, "Received cookie: " + csrf); addFormField("csrfmiddlewaretoken", csrf); return true; } private boolean openConnection() throws IOException { httpConn = (HttpURLConnection) url.openConnection(); httpConn.setUseCaches(false); httpConn.setDoOutput(true); // indicates POST method httpConn.setDoInput(true); //httpConn.setRequestProperty("Accept-Encoding", "identity"); httpConn.setFixedLengthStreamingMode(contentLength); httpConn.setRequestProperty("Connection", "Keep-Alive"); httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); outputStream = new BufferedOutputStream(httpConn.getOutputStream()); writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true); return true; } private void writeContent() throws IOException { for (FormField field : fields) { writer.append("--" + boundary).append(LINE_FEED); writer.append("Content-Disposition: form-data; name=\"" + field.name + "\"") .append(LINE_FEED); writer.append("Content-Type: text/plain; charset=" + charset).append( LINE_FEED); writer.append(LINE_FEED); writer.append(field.value).append(LINE_FEED); writer.flush(); } for (FilePart filePart : files) { String fileName = filePart.uploadFile.getName(); writer.append("--" + boundary).append(LINE_FEED); writer.append( "Content-Disposition: form-data; name=\"" + filePart.fieldName + "\"; 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(); FileInputStream inputStream = new FileInputStream(filePart.uploadFile); int bufferSize = Math.min(inputStream.available(), maxBufferSize); byte[] buffer = new byte[bufferSize]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer, 0, bufferSize)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.flush(); inputStream.close(); writer.append(LINE_FEED); writer.flush(); } writer.append("--" + boundary + "--").append(LINE_FEED); writer.close(); } } 

El uso es en gran parte el mismo que en la respuesta anterior, pero he incluido el soporte CSRF que Django usa de forma predeterminada con formularios

 boolean useCSRF = true; MultipartLargeUtility multipart = new MultipartLargeUtility(url, "UTF-8",useCSRF); multipart.addFormField("param1","value"); multipart.addFilePart("filefield",new File("/path/to/file")); List response = multipart.finish(); Log.w(TAG,"SERVER REPLIED:"); for(String line : response) { Log.w(TAG, "Upload Files Response:::" + line); } 

Esto es lo que hice para subir fotos usando una solicitud posterior.

 public void uploadFile(int directoryID, String filePath) { Bitmap bitmapOrg = BitmapFactory.decodeFile(filePath); ByteArrayOutputStream bao = new ByteArrayOutputStream(); String upload_url = BASE_URL + UPLOAD_FILE; bitmapOrg.compress(Bitmap.CompressFormat.JPEG, 90, bao); byte[] data = bao.toByteArray(); HttpClient httpClient = new DefaultHttpClient(); HttpPost postRequest = new HttpPost(upload_url); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); try { // Set Data and Content-type header for the image FileBody fb = new FileBody(new File(filePath), "image/jpeg"); StringBody contentString = new StringBody(directoryID + ""); entity.addPart("file", fb); entity.addPart("directory_id", contentString); postRequest.setEntity(entity); HttpResponse response = httpClient.execute(postRequest); // Read the response String jsonString = EntityUtils.toString(response.getEntity()); Log.e("response after uploading file ", jsonString); } catch (Exception e) { Log.e("Error in uploadFile", e.getMessage()); } } 

NOTA: Este código requiere bibliotecas. Siga las instrucciones aquí para obtener las bibliotecas.

Encontré usar okHttp mucho más fácil ya que no pude lograr que ninguna de estas soluciones funcionara: https://stackoverflow.com/a/37942387/447549

Probé las soluciones anteriores y ninguna me funcionó de la caja.

Sin embargo http://www.baeldung.com/httpclient-post-http-request . Solicitud de multipartida POST de la línea 6 trabajada en segundos

 public void whenSendMultipartRequestUsingHttpClient_thenCorrect() throws ClientProtocolException, IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpPost httpPost = new HttpPost("http://www.example.com"); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addTextBody("username", "John"); builder.addTextBody("password", "pass"); builder.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext"); HttpEntity multipart = builder.build(); httpPost.setEntity(multipart); CloseableHttpResponse response = client.execute(httpPost); client.close(); }