2016-02-05 54 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

相關問題