2016-02-05 52 views
8

在我的App Engine的后端我有一个从Google Cloud Storage从App Engine的发送图像数据到Android应用

@ApiMethod(
     name = "getProfileImage", 
     path = "image", 
     httpMethod = ApiMethod.HttpMethod.GET) 
public Image getProfileImage(@Named("imageName")String imageName){ 
    try{ 
     HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); 
     GoogleCredential credential = GoogleCredential.getApplicationDefault(); 

     Storage.Builder storageBuilder = new Storage.Builder(httpTransport,new JacksonFactory(),credential); 
     Storage storage = storageBuilder.build(); 

     Storage.Objects.Get getObject = storage.objects().get("mybucket", imageName); 

     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     // If you're not in AppEngine, download the whole thing in one request, if possible. 
     getObject.getMediaHttpDownloader().setDirectDownloadEnabled(false); 
     getObject.executeMediaAndDownloadTo(out); 

     byte[] oldImageData = out.toByteArray(); 
     out.close(); 

     ImagesService imagesService = ImagesServiceFactory.getImagesService(); 

     return ImagesServiceFactory.makeImage(oldImageData); 
    }catch(Exception e){ 
     logger.info("Error getting image named "+imageName); 
    } 
    return null; 
} 

获取图像的方法,我遇到的问题是如何获取的图像数据,当我打电话在我的Android应用程序?

由于您不能从应用程序引擎返回原语,我将其转换为Image,以便我可以在我的应用程序中调用getImageData()以获取字节[]。

但是,返回到应用程序的Image对象与应用程序引擎中的Image对象不同,因此没有getImageData()。

如何获取图像数据到我的android应用程序?

如果我创建一个对象,它有一个byte []变量,然后我设置byte []变量与字符串数据,并返回该方法的对象将工作?

更新

的图像被从Android应用程序发送。 (此代码可能或不可能是正确的,我还没有调试它尚未)

@WorkerThread 
    public String startResumableSession(){ 
     try{ 
      File file = new File(mFilePath); 
      long fileSize = file.length(); 
      file = null; 
      String sUrl = "https://www.googleapis.com/upload/storage/v1/b/lsimages/o?uploadType=resumable&name="+mImgName; 
      URL url = new URL(sUrl); 
      HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); 
      urlConnection.setRequestProperty("Authorization",""); 
      urlConnection.setRequestProperty("X-Upload-Content-Type","image/png"); 
      urlConnection.setRequestProperty("X-Upload-Content-Length",String.valueOf(fileSize)); 
      urlConnection.setRequestMethod("POST"); 

      if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK){ 
       return urlConnection.getHeaderField("Location"); 
      } 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    private long sendNextChunk(String sUrl,File file,long skip){ 
     int bytesRead, bytesAvailable, bufferSize; 
     byte[] buffer; 
     int maxBufferSize = 524287; 
     long totalBytesSent = 0; 
     try{ 
      long fileSize = file.length(); 
      FileInputStream fileInputStream = new FileInputStream(file); 
      skip = fileInputStream.skip(skip); 

      bytesAvailable = fileInputStream.available(); 
      bufferSize = Math.min(bytesAvailable, maxBufferSize); 
      totalBytesSent = skip + bufferSize; 
      buffer = new byte[bufferSize]; 

      bytesRead = fileInputStream.read(buffer, 0, bufferSize); 
      try { 
       while (bytesRead > 0) { 

        try { 
         URL url = new URL(sUrl); 
         HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); 
         urlConnection.setDoInput(true); 
         urlConnection.setDoOutput(true); 
         urlConnection.setUseCaches(false); 
         urlConnection.setChunkedStreamingMode(524287); 
         urlConnection.setRequestMethod("POST"); 
         urlConnection.setRequestProperty("Connection", "Keep-Alive"); 
         urlConnection.setRequestProperty("Content-Type","image/png"); 
         urlConnection.setRequestProperty("Content-Length",String.valueOf(bytesRead)); 
         urlConnection.setRequestProperty("Content-Range", "bytes "+String.valueOf(skip)+"-"+String.valueOf(totalBytesSent)+"/"+String.valueOf(fileSize)); 

         DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream()); 
         outputStream.write(buffer, 0, bufferSize); 

         int code = urlConnection.getResponseCode(); 

         if(code == 308){ 
          String range = urlConnection.getHeaderField("Range"); 
          return Integer.parseInt(range.split("-")[1]); 
         }else if(code == HttpURLConnection.HTTP_CREATED){ 
          return -1; 
         } 

         outputStream.flush(); 
         outputStream.close(); 
         outputStream = null; 
        } catch (OutOfMemoryError e) { 
         e.printStackTrace(); 
//      response = "outofmemoryerror"; 
//      return response; 
         return -1; 
        } 
        fileInputStream.close(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
//    response = "error"; 
//    return response; 
       return -1; 
      } 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
     return -1; 
    } 

编辑2:

显然其并不清楚,我使用端点在我的Android应用程序的人

+0

我通常使用Python,所以我不知道你这样做,在Java中,但你可以只归还从谷歌云存储所产生的资料图片网址而不是返回字节数组。以这种方式,您可以缓存配置文件url以避免始终重建它。 –

+0

由于@Maël说你不应该通过你的堆栈传递整个图像(出于性能的原因,也为了降低成本)。你是否创建图像类型?如果是,你可以发布其来源? –

+0

@BenoîtSauvère图像来自android应用程序,我用该代码更新了问题。要获取图像Url不要我必须下载图像数据吗?所以基本上我会下载图像数据两次,一次在服务器上,以获得服务Url,并再次在客户端应用程序。与仅从服务器获取图像数据相比,这样做效率不高(成本)?一旦android应用程序获取图像数据,我的计划是将图像缓存到本地(将其保存到磁盘),以便它不必再次获取图像 – tyczj

回答

1

我最终什么事做/找出你需要调用​​与端点的API调用和返回从API

例如

传回的实时数据

API调用返回Image

public Image getProfileImage(@Named("id") long id, @Named("imageName")String imageName){ 
     try{ 
      ProfileRecord pr = get(id); 
      HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); 
      GoogleCredential credential = GoogleCredential.getApplicationDefault(); 

      Storage.Builder storageBuilder = new Storage.Builder(httpTransport,new JacksonFactory(),credential); 
      Storage storage = storageBuilder.build(); 

      Storage.Objects.Get getObject = storage.objects().get("mybucket", imageName); 

     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     // If you're not in AppEngine, download the whole thing in one request, if possible. 
     getObject.getMediaHttpDownloader().setDirectDownloadEnabled(false); 
     getObject.executeMediaAndDownloadTo(out); 

     byte[] oldImageData = out.toByteArray(); 
     out.close(); 
     return ImagesServiceFactory.makeImage(oldImageData); 
    }catch(Exception e){ 
     logger.info("Error getting image named "+imageName); 
    } 
    return null; 
} 

然后在客户端我会这样称呼它得到它

Image i = pr.profileImage(id,"name.jpg").execute(); 
byte[] data = i.decodeImageData(); 
-1

您可以使用谷歌云端点此:

谷歌云端点包括工具,库和能力 塔允许您从引擎应用程序(称为API后端)生成API和客户端库,以简化客户端从其他应用程序访问数据的过程。端点使 更容易为Web客户端和移动客户端(如 Android或Apple iOS)创建Web后端。

看到https://cloud.google.com/appengine/docs/java/endpoints/

+0

这就是我正在使用的所以你没有真正回答我的问题 – tyczj

+0

我真的很抱歉,我试图帮助你不是为了满意。也许在你的问题中提到Endpoints可以避免我无法容忍的误解。 – robert

相关问题