2014-03-02 36 views
8

我想旋轉/翻轉已經坐在Google雲端存儲中的圖像。在Google App Engine中存儲旋轉/翻轉的圖像

這是的BlobKey:

BlobKey blobKey = new BlobKey(upload.getBlobKey()); 

然後我檢索圖像和應用圖像變換:

ImagesService imagesService = ImagesServiceFactory.getImagesService(); 
Image image = ImagesServiceFactory.makeImageFromBlob(blobKey); 
Transform transform = ImagesServiceFactory.makeRotate(90); 
Image newImage = imagesService.applyTransform(transform, image); 

的RAW圖像數據I可以以字節數組得到使用:

newImage.getImageData() 

直接使用GCS,我可以將它寫入雲存儲服務:

GcsFilename fileName = new GcsFilename("bucket-name", upload.getFileName()); 
GcsOutputChannel outputChannel = GcsServiceFactory.createGcsService().createOrReplace(fileName, GcsFileOptions.getDefaultInstance()); 
outputChannel.write(ByteBuffer.wrap(newImage.getImageData())); 
outputChannel.close(); 

本地我可以看到坐在appengine生成的文件夾中的旋轉圖像,我如何獲得新的服務url或objectName是爲了覆蓋原始圖像? objectName與上傳時的原始文件名相同,是blobkey,...?

更新:

我存儲在上載的GcsFilename:

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); 
Map<String,List<FileInfo>> finfos = blobstoreService.getFileInfos(req); 
String gcsFileName = finfos.get("uploadKey").get(0).getGsObjectName(); 
upload.setGcsFileName(gcsFileName); 
upload.persist(); 

的GcsFileName看起來是這樣的(本地):

/gs/bucket-name/fake-encoded_gs_key:YXVjdGlvbi1wb3J0YWwtdXBsb2Fkcy84SXp5VGpIUWlZSDY5X1Ytck5TbGtR-0f969f5b4f53a01479ff2d5eaf02fa1a (unindexed)

然後在我的旋轉方式,我做了以下:

GcsFilename fileName = new GcsFilename("bucket-name", upload.getGcsFileName()); 
GcsOutputChannel outputChannel = GcsServiceFactory.createGcsService().createOrReplace(fileName, GcsFileOptions.getDefaultInstance()); 
outputChannel.write(ByteBuffer.wrap(newImage.getImageData())); 
outputChannel.close(); 

BlobstoreService bs = BlobstoreServiceFactory.getBlobstoreService(); 
BlobKey bk = bs.createGsBlobKey(fileName.getObjectName()); 

當我打印使用bk.getKeyString()新的blobKey,我得到一個巨大的BlobKey:

encoded_gs_key:L2dzL2F1Y3Rpb24tcG9ydGFsLXVwbG9hZHMvZmFrZS1lbmNvZGVkX2dzX2tleTpZWFZqZEdsdmJpMXdiM0owWVd3dGRYQnNiMkZrY3k4NFNYcDVWR3BJVVdsWlNEWTVYMVl0Y2s1VGJHdFItMGY5NjlmNWI0ZjUzYTAxNDc5ZmYyZDVlYWYwMmZhMWE

當我嘗試:

imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(bk); 

我現在得到INVALID_BLOB_KEY:無法讀blob。

與相同:

imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(fileName.getObjectName())); 

INVALID_BLOB_KEY:無法讀取BLOB。

更新 - 測試直播:

我已經做了一些現場記錄到看能不能找準事情會出錯。

當我打印出來的GcsFilename,這就是我得到:

GcsFilename fileName = new GcsFilename("bucket-name", upload.getGcsFileName()); 
System.out.println("fileName.getObjectName(): " + fileName.getObjectName()); 
System.out.println("fileName.getBucketName(): " + fileName.getBucketName()); 

2014-03-08 09:31:35.076 [s~_____/live-1-0-2.374269833496060124].<stdout>: fileName.getObjectName(): /gs/bucket-name/L2FwcGhvc3RpbmdfcHJvZC9ibG9icy9BRW5CMlI 
2014-03-08 09:31:35.076 [s~_____/live-1-0-2.374269833496060124].<stdout>: fileName.getBucketName(): bucket-name 

然後產生新的BlobKey:

BlobstoreService bs = BlobstoreServiceFactory.getBlobstoreService(); 
BlobKey bk = bs.createGsBlobKey(fileName.getObjectName()); 

System.out.println("GSBlobKey: " + bk.getKeyString()); 

2014-03-08 09:31:37.993 [s~_____/live-1-0-2.374269833496060124].<stdout>: GSBlobKey: AMIfv94Tj3xO9hPWwMm314Id0obQs1gVWOHYVuGaaAjjMbieBUD6x0nNGbqiY8o5Jk9iLga4pPe9-8L1 

然後利用獲取新服務的網址3種不同的方法:

String newImageUrl1 = imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(fileName.getObjectName())); 
System.out.println("newImageUrl1: " + newImageUrl1); 

String newImageUrl2 = imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(bk)); 
System.out.println("newImageUrl2: " + newImageUrl2); 

String newImageUrl3 = imagesService.getServingUrl(bk); 
System.out.println("newImageUrl3: " + newImageUrl3); 


2014-03-08 09:31:38.116 [s~_____/live-1-0-2.374269833496060124].<stdout>: newImageUrl1: http://lh3.ggpht.com/My7zTT79xOltI3cMzHidx7-Us91Qlp13jdv-vJceQ_OpX3FONSr9YzI2... 
2014-03-08 09:31:38.152 [s~_____/live-1-0-2.374269833496060124].<stdout>: newImageUrl2: http://lh3.ggpht.com/My7zTT79xOltI3cMzHidx7-Us91Qlp13jdv-vJceQ_OpX3FONSr9YzI2... 
2014-03-08 09:31:38.218 [s~_____/live-1-0-2.374269833496060124].<stdout>: newImageUrl3: http://lh3.ggpht.com/My7zTT79xOltI3cMzHidx7-Us91Qlp13jdv-vJceQ_OpX3FONSr9YzI2... 

當我訪問這些URL時,我得到的是原始圖像。

當我看着雲存儲控制檯,將原始圖像坐在: 主頁/桶名稱/

旋轉後的圖像卻是坐在: 主頁/桶名// GS /桶-name/

因此,它不覆蓋原來的原因。 我猜我要創建的fileName不正確,或者我創建的GcsOutputChannel正在改變路徑? 我也很好奇爲什麼我要獲取原始圖片的網址而不是新圖片的網址?

如果我分裂原GcsFileName,只需要最後一部分,我得到一個錯誤:

GcsFilename fileName = new GcsFilename("bucket-name", upload.getGcsFileName().split("/")[3]); 

谷歌存儲文件名必須與/ GS前綴/

任何想法?

解決方案

Retreive的blobKey使用:

BlobKey blobKey = blobstoreService.createGsBlobKey("/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName()); 

...即使fileName.getObjectName()已經包含了 「/ GS /桶名稱/」 的對象名的前面。當把它打印到標準輸出時,你的fileName應該包含/ gs/bucket-name /兩次,很奇怪,但是它可以工作。

使用的blobKey,正確的服務URL創建

+1

嘿月從 「假encoded_gs_key」 我明白,你是在本地開發服務器上進行測試。某些GCS和ImageService功能在此處不可用。 您是否對GAE生產應用程序進行過相同的測試? – David

+0

旋轉的圖像正在寫入不正確的位置,如果我可以修復,那麼旋轉將是100%,我已經更新了這個問題。 –

+1

Hey Jan,「getObjectName()」不應該返回bucket名稱,也不應該在開始時返回「/ gs」。你確定你的日誌輸出的是對象名稱而不是toString()方法的結果嗎? – David

回答

3

要覆蓋原始圖像,你只需要指定相同的雲存儲文件名。

我知道您已經通過App Engine通過BlobStore API將圖像上傳到雲存儲。要獲得原始圖像的實際文件名,你必須在上傳的servlet添加以下代碼

Map<String,List<BlobInfo>> uploadInfos = getFileInfos(httpServletRequest); 
    String theGCSFilename = uploadInfos.get("yourFileName").getGsObjectName(); 

請注意,如果你不想覆蓋原來的文件,而是希望提供的服務URL給客戶,您可以:

  • 這樣使用ImageService:

    ImagesService imagesService = ImagesServiceFactory.getImagesService(); 
    String url = imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(java)); 
    
  • 創建自定義GCSServingServlet誰將使用BlobstoreService.serve()方法從Blobstore或雲存儲提供文件。在這種情況下,您必須自己檢查權限。請注意,您可以使用BlobStoreService.createGSBlobKey()GCSFilename創建BlobKey

  • 使用雲存儲服務的URL:

+0

我已經使用片段更新了問題,並且卡住了,感覺就像我差不多在那裏。 –