从Android客户端将图像存储到Blobstore并检索blobkey并上传URL以存储在Datastore中。 – GAE

在我的Android应用程序中,我想将图像上传到Blobstore,然后检索上传URL和图像的Blobkey,这样我就可以将Blobkey存储在DataStore中。

我试过这段代码,但我的图片没有上传:

Servlet(返回上传url)

BlobstoreService blobstoreService = BlobstoreServiceFactory .getBlobstoreService(); public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { UploadOptions uploadOptions = UploadOptions.Builder .withGoogleStorageBucketName("photobucket11") .maxUploadSizeBytes(1048576); String blobUploadUrl = blobstoreService.createUploadUrl("/upload", uploadOptions); // String blobUploadUrl = blobstoreService.createUploadUrl("/uploaded"); resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType("text/plain"); PrintWriter out = resp.getWriter(); out.print(blobUploadUrl); } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { doGet(req, resp); } 

代码:Android客户端

 Bitmap bmp = BitmapFactory.decodeFile(imagePath); ByteArrayOutputStream out = new ByteArrayOutputStream(); bmp.compress(CompressFormat.JPEG, 75, out); byte[] imgByte = out.toByteArray(); String encodedImage = Base64.encodeToString(imgByte, Base64.DEFAULT); HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet( "app-url/ImgUpload"); HttpResponse response = httpClient.execute(httpGet); HttpEntity urlEntity = response.getEntity(); InputStream in = urlEntity.getContent(); String str = ""; while (true) { int ch = in.read(); if (ch == -1) break; str += (char) ch; } 

这将以/_ah/upload/akjdhjahdjaudshgaajsdhjsdhforms返回上传URL,我可以使用它来存储图像。

此代码使用url存储图像:

 httpClient = new DefaultHttpClient(); HttpPost postRequest = new HttpPost(str); ByteArrayBody bab = new ByteArrayBody(imgByte, "forest.jpg"); MultipartEntity reqEntity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE); reqEntity.addPart("uploaded", bab); reqEntity.addPart("photoCaption", new StringBody("sfsdfsdf")); postRequest.setEntity(reqEntity); response = httpClient.execute(postRequest); BufferedReader reader = new BufferedReader( new InputStreamReader( response.getEntity().getContent(), "UTF-8")); String sResponse; StringBuilder s = new StringBuilder(); while ((sResponse = reader.readLine()) != null) { s = s.append(sResponse); } 

在这里,如果我检查String s值,它显示为null 。 这意味着它返回一个空响应。 我不知道这段代码有什么问题。 请指导我解决这个问题。

经过多次尝试,我解决了这个问题。 要在blobstore中存储图像,首先android需要向servlet发出请求,这将生成上传URL:

Android客户端:它将请求生成url并从servlet获取url

 HttpClient httpClient = new DefaultHttpClient(); //This will invoke "ImgUpload servlet HttpGet httpGet = new HttpGet("my-app-url/ImgUpload"); HttpResponse response = httpClient.execute(httpGet); HttpEntity urlEntity = response.getEntity(); InputStream in = urlEntity.getContent(); String str = ""; while (true) { int ch = in.read(); if (ch == -1) break; str += (char) ch; } 

ImgUpload.java – 生成url并向客户端发送响应的Servlet

 BlobstoreService blobstoreService = BlobstoreServiceFactory .getBlobstoreService(); public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { //"uploaded" is another servlet which will send UploadUrl and blobkey to android client String blobUploadUrl = blobstoreService.createUploadUrl("/uploaded"); resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType("text/plain"); PrintWriter out = resp.getWriter(); out.print(blobUploadUrl); } 

在android客户端中,将下面的代码上传图像写入从上面的servlet返回的响应。

 //Save image to generated url HttpPost httppost = new HttpPost(str); File f = new File(imagePath); FileBody fileBody = new FileBody(f); MultipartEntity reqEntity = new MultipartEntity(); reqEntity.addPart("file", fileBody); httppost.setEntity(reqEntity); response = httpClient.execute(httppost); //Here "uploaded" servlet is automatically invoked urlEntity = response.getEntity(); //Response will be returned by "uploaded" servlet in JSON format in = urlEntity.getContent(); str = ""; while (true) { int ch = in.read(); if (ch == -1) break; str += (char) ch; } JSONObject resultJson = new JSONObject(str); String blobKey = resultJson.getString("blobKey"); String servingUrl = resultJson.getString("servingUrl"); 

uploaded.java- servlet返回图像的Uploadurl和Blobkey

 BlobstoreService blobstoreService = BlobstoreServiceFactory .getBlobstoreService(); public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { List blobs = blobstoreService.getUploads(req).get("file"); BlobKey blobKey = blobs.get(0); ImagesService imagesService = ImagesServiceFactory .getImagesService(); ServingUrlOptions servingOptions = ServingUrlOptions.Builder .withBlobKey(blobKey); String servingUrl = imagesService.getServingUrl(servingOptions); resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType("application/json"); JSONObject json = new JSONObject(); json.put("servingUrl", servingUrl); json.put("blobKey", blobKey.getKeyString()); PrintWriter out = resp.getWriter(); out.print(json.toString()); out.flush(); out.close(); } catch (JSONException e) { e.printStackTrace(); } } 

感谢zanky我设法理解它并且我想添加我的代码,因为在他的答案中不赞成某些代码,而且一些代码需要更多的解释,如重写和asynctask。 顺便说一句,由于localhost和IP混淆,代码可能无法在本地服务器上运行。 准备好后试试app引擎。

Servlet-1 BlobUrlGet。 这将是appengine方面。 此servlet为客户端代码中的post方法生成上传URL。

 public class BlobUrlGet extends HttpServlet{ BlobstoreService blServ = BlobstoreServiceFactory.getBlobstoreService(); public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { String blobUploadUrl = blServ.createUploadUrl("/blobupload"); resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType("text/plain"); PrintWriter out = resp.getWriter(); out.print(blobUploadUrl); } } 

Servlet-2 BlobUpload当对blobstore发布post时,将自动调用此代码。 因此,它将为我们提供blobkey和服务URL以便稍后下载图像。

 public class BlobUpload extends HttpServlet { BlobstoreService blobstoreService = BlobstoreServiceFactory .getBlobstoreService(); @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { List blobs = blobstoreService.getUploads(req).get("photo"); BlobKey blobKey = blobs.get(0); ImagesService imagesService = ImagesServiceFactory.getImagesService(); ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey); String servingUrl = imagesService.getServingUrl(servingOptions); resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType("application/json"); JSONObject json = new JSONObject(); json.put("servingUrl", servingUrl); json.put("blobKey", blobKey.getKeyString()); PrintWriter out = resp.getWriter(); out.print(json.toString()); out.flush(); out.close(); } catch (JSONException e) { e.printStackTrace(); } } } 

Android客户端端代码。 这个asynctask将调用servlet并使用它获得的信息向blobstore发布post。

  private class GetBlobUrlTask extends AsyncTask { @Override protected Void doInBackground(Void... arg0){ HttpClient httpClient = new DefaultHttpClient(); //This will invoke "ImgUpload servlet HttpGet httpGet = new HttpGet("http://img.androidcookie.com/android/jpeg), foto2.jpg"); httppost.setEntity(reqEntity.build()); response = httpClient.execute(httppost); //Here "uploaded" servlet is automatically invoked str = EntityUtils.toString(response.getEntity()); JSONObject resultJson = new JSONObject(str); blobKey = resultJson.getString("blobKey"); servingUrl = resultJson.getString("servingUrl"); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } } 

毕竟我们需要更新web.xml才能执行servlet。

   BlobUrlGet PUT_YOUR_PACKAGE_NAME.BlobUrlGet   BlobUrlGet /bloburlget   BlobUpload PUT_YOUR_PACKAGE_NAME.BlobUpload   BlobUpload /blobupload  

我在Android Studio中使用端点,感谢SAVANTE,我可以完成我的代码,但我不得不进行小的调整。

在Servlet 1中:我使用了Endpoints,我可以在我的方法中轻松处理OAuth2:

 @ApiMethod(name = "getBlobURL", scopes = {Constants.EMAIL_SCOPE}, clientIds = {Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID, com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID}, audiences = {Constants.ANDROID_AUDIENCE}) public BlobAttributes getBlobURL(User user) throws UnauthorizedException, ConflictException{ //If if is not null, then check if it exists. If yes, throw an Exception //that it is already present if (user == null){ throw new UnauthorizedException("User is Not Valid"); } BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); String blobUploadUrl = blobstoreService.createUploadUrl("/blobupload"); //BlobAttributes is a class BlobAttributes ba= new BlobAttributes(); ba.setBlobURL(blobUploadUrl); return ba; } 

我的后端在端点Android Studio,不要让我使用JSONObject为这个rason我自己创建Json:在Servlet 2中:

 String myJson = "{'servingUrl': '" + servingUrl + "', 'blobKey': '" + blobKey.getKeyString() + "'}"; PrintWriter out = resp.getWriter(); out.print(myJson); out.flush(); out.close(); 

我希望为其他人工作,我花了48个小时试图理解和操作Blobstore。

编辑:

要从客户端进行经过身份validation的呼叫,这是使用Google凭据的方式:

 accountName = settings.getString(start.KEY_ACCOUNT_NAME, null); //Email account that you before save it credential = GoogleAccountCredential.usingAudience(getActivity(), start.WEB_CLIENT_ID); //WEB_CLIENT_ID is your WEB ID in Google Console credential.setSelectedAccountName(accountName); 

构建您的Endpoint时,请填写您的凭证:

 PostEndpoint.Builder builder = new PostEndpoint.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), credential) .setRootUrl(getActivity().getString(R.string.backend_url_connection)); myApiService = builder.build(); 

要获取客户端的帐户名称,请使用Plus API

 accountName = Plus.AccountApi.getAccountName(mGoogleApiClient); 

阅读评论中的链接,使用Google文档可以很好地理解这一点。