I am trying to write an Android application that will take a picture, put the data (byte[]) in an object along with some metadata, and post that to an AppEngine server where
Not exactly sure if this is what you want but this will submit an image in the same way that your browser would submit an image as part of a form. You will have to download httmime-4.1.3.jar and add it as a referenced library in your project.
Bitmap bm;//whatever bitmap you are trying to send
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(CompressFormat.JPEG, 75, bos);
byte[] data = bos.toByteArray();
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("http://yourwebsite.com/whatever");
ByteArrayBody bab = new ByteArrayBody(data, "image name");
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("photo", bab);//"photo" is the name of the field that the image is submitted as.
postRequest.setEntity(reqEntity);
try {
HttpResponse response = httpClient.execute(postRequest);
} catch (ClientProtocolException e) {
Log.e("asdf", e.getMessage(), e);
} catch (IOException e) {
Log.e("asdf", e.getMessage(), e);
}
1.You can encode the byte[] to base64 using:
http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html
2.Send that data with a HTTP POST request to your AppEngine servlet.
3.Configure AppEngine to accept a servlet.
4.Then you have the choice to save it to the Datastore or the Blobstore. -I prefer the blobstore for these kinds of things.
5.Decode the base64 string server side.
6.From there on you'l need to cut up your string into smaller pieces and write each piece to the blobstore.
Here's some code for writing it to the blobstore.
byte[] finalImageArray = null;
try {
finalImageArray = Base64.decode(finalImageData.getBytes()); //finalImageData is the string retrieved from the HTTP POST
} catch (Base64DecoderException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try{
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile file = fileService.createNewBlobFile("image/png");
FileWriteChannel writeChannel = fileService.openWriteChannel(file, true);
int steps = (int) Math.floor(finalImageArray.length/1000);
int current = 0;
for(int i = 0; i < 1000; i++){
writeChannel.write(ByteBuffer.wrap(Arrays.copyOfRange(finalImageArray, current, steps+current)));
current = current + steps;
}
writeChannel.write(ByteBuffer.wrap(Arrays.copyOfRange(finalImageArray, current, finalImageArray.length))); //The reason it's cut up like this is because you can't write the complete string in one go.
writeChannel.closeFinally();
blobKey = fileService.getBlobKey(file);
if(blobKey == null)
blobKey = retryBloBKey(file); //My own method, AppEngine tends to not return the blobKey once a while.
}
catch(Exception e){
logger.log(Level.SEVERE,e.getMessage());
}
return blobKey.getKeyString();
Write a servlet where you retrieve the image data with the provided key.
Enjoy your beautiful code :)
//The reason i save it in binary is because that gives me options to play with the image api, you can also choose to save it in the base64 format.
As code is provided by three person so you can select any of them(or you will get a lot of example on google). There are three possiblity 1)first you have image in your sdcard
2)you are downloading image from server and then sending
3)Images are store in DataBase as blob
The best approach considering each case-
1)If your Image is store in sdcard then simply fecth image Convert into bitmap ->byteArray ->String and send to server
2)If you are downloading images from server and then sending to another URL.Then download all image URL store in DataBase Table.Later on when you need to send to server fetch url,download image and store in cache memory.then similarly send it server and refresh cache memory
3)Its recommend not to store a lot of image in DB.But in case you have neccessity of doing it then getBlob convert into byte array and send to server
Sending Image To server
Reading blob
Reading from sdcard
List<Integer> drawablesId = new ArrayList<Integer>();
int picIndex=12345;
File sdDir = new File("/sdcard/pictures");
File[] sdDirFiles = sdDir.listFiles();
for(File singleFile : sdDirFiles)
{
Drawable.createFromPath(singleFile.getAbsolutePath());
/ you can create Bitmap from drawable
}
Hope it will help you
You just need to do a Http-FileUpload which in a special case of a POST. There is no need to uuencode the file. No need to use a special lib/jar No need to save the object to disk (regardless that the following example is doing so)
You find a very good explanation of Http-Command and as your special focus "file upload" under
Using java.net.URLConnection to fire and handle HTTP requests
The file upload sample from there follows (watch "send binary file") and it is possible to add some companion data either
String param = "value";
File textFile = new File("/path/to/file.txt");
File binaryFile = new File("/path/to/file.bin");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
OutputStream output = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!
// Send normal param.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(param).append(CRLF).flush();
// Send text file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF).flush();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(textFile), charset));
for (String line; (line = reader.readLine()) != null;) {
writer.append(line).append(CRLF);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
writer.flush();
// Send binary file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName()).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
InputStream input = null;
try {
input = new FileInputStream(binaryFile);
byte[] buffer = new byte[1024];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
output.flush(); // Important! Output cannot be closed. Close of writer will close output as well.
} finally {
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
writer.append(CRLF).flush(); // CRLF is important! It indicates end of binary boundary.
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF);
} finally {
if (writer != null) writer.close();
}
Regarding the second part of your question. When successful uploading the file (I use apache common files), it is not a big deal to deliver a blob as an image.
This is how to accept a file in a servlet
public void doPost(HttpServletRequest pRequest, HttpServletResponse pResponse)
throws ServletException, IOException {
ServletFileUpload upload = new ServletFileUpload();
try {
FileItemIterator iter = upload.getItemIterator (pRequest);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String fieldName = item.getFieldName();
InputStream stream = item.openStream();
....
stream.close();
}
...
And this code delivers an image
public void doGet (HttpServletRequest pRequest, HttpServletResponse pResponse) throws IOException {
try {
Blob img = (Blob) entity.getProperty(propImg);
pResponse.addHeader ("Content-Disposition", "attachment; filename=abc.png");
pResponse.addHeader ("Cache-Control", "max-age=120");
String enc = "image/png";
pResponse.setContentType (enc);
pResponse.setContentLength (img.getBytes().length);
OutputStream out = pResponse.getOutputStream ();
out.write (img.getBytes());
out.close();
I hope this code fragments help to answer your questions
The Android Asynchronous Http library provides a method of uploading files to a web service. I've used it in my projects with great success.
Sounds like you need a web service method that takes an ID parameter and returns a file. You would store your blobs in the database table indexed with ID so that they can be referenced.