I am having a doubt on how can I post a data where my REST end point URL is like below:
http://my.domain.com/Upload/{ID}/{IMAGE_CONTENT_AS_BYTE_ARRAY}
I need to send the the Image content as byte array string to this end point method. But Since the charater length can go beyond 2000 character length, I may not be able to send the the IMAGE if its huge since everything goes as part of URL string. How can I put the data of IMAGE_CONTENT_AS_BYTE_ARRAY .
Also I don't have any key for this so that I can put it in namevalue pair.Please suggest!
Try this code:
MultipartEntityBuilder multipartEntity;
String URL = "My server url";
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
bitmap.compress(CompressFormat.JPEG, 75, byteArrayOutputStream);
byte[] byteData = byteArrayOutputStream.toByteArray();
ByteArrayBody byteArrayBody = new ByteArrayBody(byteData, "image"); // second parameter is the name of the image )
// send the package
multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("image", byteArrayBody);
The best way to upload images or files is using multi part data format.
Here is a sample code for uploading image.
public static void postMultiPart(String url, File image)
{
final android.net.http.AndroidHttpClient client = android.net.http.AndroidHttpClient.newInstance("sample");
// enable redirects
HttpClientParams.setRedirecting(client.getParams(), true);
final String encoded_url = encodeURL(url);
final org.apache.http.client.methods.HttpPost post = new org.apache.http.client.methods.HttpPost(encoded_url);
MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
mpEntity.addPart("profile", new FileBody(image));
post.setEntity(mpEntity);
org.apache.http.HttpResponse response;
try {
response = client.execute(post);
final int statusCode = response.getStatusLine().getStatusCode();
if (!(statusCode == org.apache.http.HttpStatus.SC_OK || statusCode == org.apache.http.HttpStatus.SC_CREATED)) {
Log.i("Error:","Check....."+"Error " + statusCode + " while posting data to " + encoded_url + "\nreason phrase: " + response.getStatusLine().getReasonPhrase());
return;
}
Log.i("SUCCESS:","Check....."+Base64.encodeToString(md.digest(), Base64.DEFAULT));
} catch (IOException e) {
} finally {
client.close();
}
}
Related
I am running a flask server at the backend. I want to read the image from mobile app and send it to the server to detect faces.
This is the java code(client side) for sending image as bytes -
public class client {
public static void main(String [] args) throws Exception{
String url = "http://127.0.0.1:8080/facial";
// 2. create obj for the URL class
URL obj = new URL(url);
// 3. open connection on the url
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type","image/jpeg");
con.setDoInput(true);
con.setDoOutput(true);
try {
System.out.println("Reading image from disk. ");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.flush();
File file = new File("jpeg.jpg");
BufferedImage image1 = ImageIO.read(file);
ImageIO.write(image1, "jpg", baos);
baos.flush();
System.out.println(baos.size());
byte[] bytes = baos.toByteArray();
baos.close();
System.out.println("Sending image to server. ");
OutputStream out = con.getOutputStream();
DataOutputStream image = new DataOutputStream(out);
image.writeInt(bytes.length);
image.write(bytes, 0, bytes.length);
System.out.println("Image sent to server. ");
image.close();
// close the output stream
out.close();
}catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
// define object for the reply from the server
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
//Get response from server
int responseCode = con.getResponseCode();
System.out.println("Response Code : " + responseCode);
// read in the response from the server
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
System.out.println(inputLine);
}
// close the input stream
in.close();
}
}
This is my server code -
def get_facial(data):
face_api_url = 'https://southeastasia.api.cognitive.microsoft.com/face/v1.0/detect'
# Set image_url to the URL of an image that you want to analyze.
headers = {'Ocp-Apim-Subscription-Key': subscription_key,
"Content-Type":"application/octet-stream"
}
params = {
'returnFaceId': 'true',
'returnFaceLandmarks': 'false',
'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' +
'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise'
}
response = requests.post(face_api_url, params=params, headers=headers, data=data)
faces = response.json()
res={}
import pdb; pdb.set_trace()
res["status"] = '200'
res["num"] = str(len(faces))
return res
#app.route('/facial',methods=['POST'])
def facial():
import pdb; pdb.set_trace()
data=bytes(request.get_data())
res={}
try:
res = get_facial(data)
except:
res['status'] = '404'
print(res)
return json.dumps(res)
After examining - I sent the same image from another python file and checked the size of the data. It was 102564 bytes and it works but
the same image read and sent from java code is 106208 bytes. I don't know where exactly the mistake is.
Any help is appreciated !!:-)
I found a quick fix to this problem -
Path path = Paths.get("jpeg.jpg");
byte[] fileContents = Files.readAllBytes(path);
image.write(fileContents, 0, fileContents.length);
I don't exactly know why reading from imageio fails. My guess is that its also reading the file headers of the jpg file.
I have code to send text and multiple image in one request to server, my case is, I loop through local db to get the data and multiple image so I can use addPart(key, textdata); for the text data and addPart(key, filename, inputstream, "application/octet-stream"); for the image data. But the problem is when I have more than one image in one request I only able to send one of them. Here are my complete code. The main problem happens on line 31 when I have more than one image it only send one of them. I will appreciate any help. Thank you.
The problem I think is might be here
reqEntity.addPart("myFile", yourImage);
In this your key(myFile) remains the same for all the images. so when your images are more than one, it keeps on overwriting the previous image. So I think, you should attach index with your key(starting from 0,1 and so on), something like this for example
reqEntity.addPart("myFile_"+i, yourImage);
And also send the image_count to server along with images,so that, it will get to know how many images you are actually sending and by having a simple for loop at the server end,they will be able to get all these images. hope this helps.
Try this way
String sResponse = "";
String url = "http://www.api.in/rpcs/uploadfiles/?";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
options1.inPreferredConfig = Bitmap.Config.ARGB_8888;
byte[] data1 = null,data2= null,data3= null,data4= null,data5= null;
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_0"))
{ up_image1 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_0", "");
bitmap = BitmapFactory.decodeFile(up_image1, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos1);
data1 = bos1.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_1"))
{ up_image2 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_1", "");
bitmap = BitmapFactory.decodeFile(up_image2, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos2);
data2 = bos2.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_2"))
{ up_image3 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_2", "");
bitmap = BitmapFactory.decodeFile(up_image3, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos3);
data3 = bos3.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_3"))
{ up_image4 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_3", "");
bitmap = BitmapFactory.decodeFile(up_image4, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos4);
data4 = bos4.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_4"))
{ up_image5 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_4", "");
bitmap = BitmapFactory.decodeFile(up_image5, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos5);
data5 = bos5.toByteArray();
}
entity.addPart("post_id", new StringBody(post_id));
entity.addPart("user_id", new StringBody(user_id));
entity.addPart("cat_id", new StringBody(category));
if(data1!=null){
entity.addPart("files[]", new ByteArrayBody(data1,"image/jpeg", "u1.jpg"));
}
if(data2!=null){
entity.addPart("files[]", new ByteArrayBody(data2,"image/jpeg", "u2.jpg"));
}
if(data3!=null){
entity.addPart("files[]", new ByteArrayBody(data3,"image/jpeg", "u3.jpg"));
}
if(data4!=null){
entity.addPart("files[]", new ByteArrayBody(data4,"image/jpeg", "u4.jpg"));
}
if(data5!=null){
entity.addPart("files[]", new ByteArrayBody(data5,"image/jpeg", "u5.jpg"));
}
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null)
{
s = s.append(sResponse);
}
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
return s.toString();
}else
{
return "{\"status\":\"false\",\"message\":\"Some error occurred\"}";
}
I'm trying to upload some photos taken by an application in a distant database. To be clear :
I take a piture from my app
I send if to a web service (witten in .net, svc file)
The WS upload it in the database
The way i'm doing it : i'm sending the byte[] recovered from the picture that way
String url = MyAddress + "insert_img?login='"
+ login_result + "'&epc='" + code + "'&title='" + t
+ "'&image='" + base64EncodedString + "'&descrip='" + d
+ "'";
BufferedReader inStream = null;
System.out.println(url);
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpR = new HttpGet(url);
httpR.setHeader("Accept", "application/json");
httpR.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(httpR);
My problem is that I have to compress A LOT the picture in order it to be send. The picture, or base64EncodedString field, is created like that :
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
mImageView.setImageDrawable(null);
mImageView.setImageBitmap(thumbnail);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 1, baos);
byte[] outputByteArray = baos.toByteArray();
base64EncodedString = Base64.encodeToString(outputByteArray, Base64.NO_WRAP + Base64.URL_SAFE);
As you can see, the image is very very very compressed, and when I recover it it's more or less a 4-colors stamp. And if I do not compress it a lot, image is not inserted.
So first of all : Am I doing it the right way to deal ? And also, why is there no insertion when the picture is too big and how, if possible, to track the error ?
Thanks !
EDIT :
I've modified my code that way, server side :
public string insert_report(Stream stream)
{
string login = "";
string epc = "";
string title = "";
string image = "";
string descrip = "";
MultipartParser parser = new MultipartParser(stream);
Entities entities = new Entities();
string res = "";
if (parser != null && parser.Success)
{
res += parser.Filename;
foreach (var content in parser.MyContents)
{
string name = content.PropertyName;
string str = Encoding.UTF8.GetString(content.Data);
res += "name : " + name +"---";
res += "content : " + str+"---";
if (name.Contains("login"))
{
login = str;
}
if (name.Contains("epc"))
{
epc = str;
}
if (name.Contains("title"))
{
title = str;
}
if (name.Contains("image"))
{
image = str;
}
if (name.Contains("descrip"))
{
descrip = str;
}
}
}
res+= " res returned by server : "+ entities.insert_report(login, epc, title, image, descrip);
entities.SaveChanges();
return res;
}
But there are some problems : the insert_report function return -1... How do I recover the error given by that function ?
Do you receive 414 (Request-URI Too Long) error? You should use HTTP POST method to upload your images as POST body - no Base64 encoding will be also required. Look at https://stackoverflow.com/a/7632849/2714032
I'm sending images and json text from the android client to a tomcat server and the other way around by using Multipart HttpPost's. Sending a Multipart Entity to the server is no big deal, because you can process the parts easily using request.getPart(<name>). But at the client side you can only access the response as a Stream. So I end up appending both, the JSON string and the image to the same ServletOutputStream and have to parse them by hand on the client side. I found apache-mime4j in the web but its hardly documented and I cant find a single example how to use it.
On the server side I build the response like this:
ServletResponse httpResponse = ctx.getResponse();
ResponseFacade rf = (ResponseFacade) httpResponse;
rf.addHeader("Access-Control-Allow-Origin", "*");
rf.addHeader("Access-Control-Allow-Methods", "POST");
rf.addHeader("content-type", "multipart/form-data");
httpResponse.setCharacterEncoding("UTF-8");
MultipartResponse multi = new MultipartResponse((HttpServletResponse) httpResponse);
ServletOutputStream out = httpResponse.getOutputStream();
multi.startResponse("text/plain");
out.println(CMD + "#" + content);
multi.endResponse();
multi.startResponse("image/jpeg");
out.write(data);
multi.endResponse();
multi.finish();
ctx.complete();
And on the client side on Android I want to access the text and the image data:
InputStream is = response.getEntity().getContent();
MimeStreamParser parser = new MimeStreamParser();
MultipartContentHandler con = new MultipartContentHandler();
parser.setContentHandler(con);
try {
parser.parse(is);
String json = con.getJSON(); //get extracted json string
byte[] imgBytes = con.getBytes(); //get extracted bytes
} catch (MimeException e) {
e.printStackTrace();
} finally {
is.close();
}
class MultipartContentHandler implements ContentHandler{
public void body(BodyDescriptor bd, InputStream in) throws MimeException, IOException {
//if MIME-Type is "text/plain"
// process json-part
//else
// process image-part
}
In the method body(BodyDescriptor bd, InputStream in) my whole response is treated as text\plain mime type. So I finally have to parse every byte manually again and the whole apache-mime4j is useless. Can you tell me what I am doing wrong? Thanks!
Ok i finally solved it myself. No here's what i did:
First I need to create a multipart/mixed Response at the server side. It can be done using apache-mime-4j API:
ServletResponse httpResponse = ctx.getResponse();
ResponseFacade rf = (ResponseFacade) httpResponse;
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("multipart/mixed");
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, "SEPERATOR_STRING",Charset.forName("UTF-8"));
entity.addPart("json", new StringBody(CMD + "#" + content, "text/plain", Charset.forName("UTF-8")));
entity.addPart("image", new ByteArrayBody(data, "image/jpeg", "file"));
httpResponse.setContentLength((int) entity.getContentLength());
entity.writeTo(httpResponse.getOutputStream());
ctx.complete();
Now at the client side to access the MIME-Parts of the HttpResponse I use the javax.mail API.
ByteArrayDataSource ds = new ByteArrayDataSource(response.getEntity().getContent(), "multipart/mixed");
MimeMultipart multipart = new MimeMultipart(ds);
BodyPart jsonPart = multipart.getBodyPart(0);
BodyPart imagePart = multipart.getBodyPart(1);
But you can't use the native API, instead take this one http://code.google.com/p/javamail-android/
Now you can proceed handling your individual parts.
It is also possible with apache-mime-4j:
HttpURLConnection conn = ...;
final InputStream is = conn.getInputStream();
try {
final StringBuilder sb = new StringBuilder();
sb.append("MIME-Version: ").append(conn.getHeaderField("MIME-Version")).append("\r\n");
sb.append("Content-Type: ").append(conn.getHeaderField("Content-Type")).append("\r\n");
sb.append("\r\n");
parser.parse(new SequenceInputStream(new ByteArrayInputStream(sb.toString().getBytes("US-ASCII")), is));
} catch (final MimeException e) {
e.printStackTrace();
} finally {
is.close();
}
I need to know the BEST way to load a bitmap and send it via http as a string, because i want to store it in a database. So could you help me with any ideas, please?
Thanks in advance, Regards
I had something this:
public byte[] ConvertBitmaptoBits(Bitmap src)
{
try{
ByteArrayOutputStream os=new ByteArrayOutputStream();
src.compress( android.graphics.Bitmap.CompressFormat.PNG, 100, (OutputStream)os );
src.compress(Bitmap.CompressFormat.PNG, 100, os); //bm is the bitmap object
byte[] b = os.toByteArray();
return b;
}catch(Throwable e)
{
//Toast.makeText(this, "Error en ConvierteBitmapAString: " + e.getMessage(), 30);
Log.v("ConvierteBitmapACadena", "Error al Convertir la imagen a Cadena: " + e.getMessage());
return null;
}
}
In my SEND method i had something like this:
public void Send() //throws Exception
{
try
{
InputStreamBody isb=null;
StringBody sImageString=null;
Resources r = this.getResources();
Bitmap bmp = BitmapFactory.decodeResource(r, R.drawable.icon);
byte[] objImageBits = ConvertBitmaptoBits(bmp);
if(objImageBits !=null ){
isb = new InputStreamBody(new ByteArrayInputStream(objImageBits), "uploadedFile");
}
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(strPath);
SimpleDateFormat sdfDateTime = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
String strCurDate = sdfDateTime.format(new Date(System.currentTimeMillis()));
StringBody sCurDate = new StringBody(strCurDate);
MultipartEntity multipartContent = new MultipartEntity();
if(objImageBits !=null)
{
multipartContent.addPart("uploadedFile", isb);
}
multipartContent.addPart("fechaequipo", sCurDate);
postRequest.setEntity(multipartContent);
HttpResponse response = httpClient.execute(postRequest);
response.getEntity().getContent().close();
}
catch (Throwable e)
{
Log.v("executeMultipartPost", "Error in executeMultipartPost: " + e.getMessage());
}
}
But it seems i am not getting the uploadedFile. This is my php script:
$file2 = (isset($_POST['uploadedFile'])) ? ( $_POST['uploadedFile'] ):('');
$fechaequipo = (isset($_POST['fechaequipo']) ) ? ( $_POST['fechaequipo'] ):('');
$fp = null;
$log_file = 'log.txt';
if (!$fp)
$fp = fopen($log_file, 'a') or exit("No se puede abrir: $log_file!");
fwrite($fp, "<INI LOG>" . date("d/m/Y") ."\n\r");
fwrite($fp, "Date : ". $fechaequipo . "\n\r");
fwrite($fp, "File2 : " . $file2 . "\n\r");
fwrite($fp, "<END LOG>" . date("d/m/Y") ."\n\r");
fclose($fp);
?>
Do I'm doing anything wrong? Thanks in advance!!!
A similar question (in a sense) is here.
You convert you image to base64, then send to a server however you like. The server can then decode the string to an image. (With PHP, that'd be base64-decode).
Bear in mind that base64 encoding increases the size of the data transferred by about 33%.