简体   繁体   English

在Google App Engine中存储旋转/翻转的图像

[英]Storing rotated / flipped images in Google App Engine

I'm trying to rotate / flip an image that is already sitting inside Google Cloud Storage. 我正在尝试旋转/翻转已经位于Google Cloud Storage内部的图像。

This is the blobkey: 这是Blobkey:

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

Then I retrieve the image and apply an image transform: 然后,我检索图像并应用图像变换:

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

The RAW image data I can get in a byte array using: 我可以使用以下方式将字节图像获取为字节数组:

newImage.getImageData()

Using GCS directly, I can write it to the cloud storage service: 直接使用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();

Locally I can see the rotated image sitting inside the appengine-generated folder, how do I get the new serving url or what should the objectName be in order to overwrite the original image? 在本地,我可以看到旋转的图像位于appengine生成的文件夹中,如何获得新的服务url或objectName应该是什么以覆盖原始图像? Is the objectName the same as the original filename when it was uploaded, is it the blobkey, ...? objectName与上载时的原始文件名是否相同,是否为Blobkey,...?

Update: 更新:

I'm storing the GcsFilename upon upload: 上传时,我将存储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();

The GcsFileName looks like this (locally): GcsFileName看起来像这样(本地):

/gs/bucket-name/fake-encoded_gs_key:YXVjdGlvbi1wb3J0YWwtdXBsb2Fkcy84SXp5VGpIUWlZSDY5X1Ytck5TbGtR-0f969f5b4f53a01479ff2d5eaf02fa1a (unindexed) / gs /存储桶名称/ fake-encoded_gs_key:YXVjdGlvbi1wb3J0YWwtdXBsb2Fkcy84SXp5VGpIUWlZSDY5X1Ytck5TbGtR-0f969f5b4f53a01479ff2d5eaf02fa1a)

Then inside my rotate method, I do the following: 然后在我的rotate方法中,执行以下操作:

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());

When I print the new blobKey using bk.getKeyString(), I get an enormous blobkey: 当我使用bk.getKeyString()打印新的blobKey时,我得到了一个巨大的blobkey:

encoded_gs_key:L2dzL2F1Y3Rpb24tcG9ydGFsLXVwbG9hZHMvZmFrZS1lbmNvZGVkX2dzX2tleTpZWFZqZEdsdmJpMXdiM0owWVd3dGRYQnNiMkZrY3k4NFNYcDVWR3BJVVdsWlNEWTVYMVl0Y2s1VGJHdFItMGY5NjlmNWI0ZjUzYTAxNDc5ZmYyZDVlYWYwMmZhMWE encoded_gs_key:L2dzL2F1Y3Rpb24tcG9ydGFsLXVwbG9hZHMvZmFrZS1lbmNvZGVkX2dzX2tleTpZWFZqZEdsdmJpMXdiM0owWVd3dGRYQnNiMkZrY3k4NFNYcDVWR3BJVVdsWlNEWTVYMVl0Y2s1VGJHdFItMGY5NjlmNWI0ZjUzYTAxNDc5ZmYyZDVlYWYwMmZhMWE

When I try: 当我尝试:

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

I now get a INVALID_BLOB_KEY: Could not read blob. 我现在得到一个INVALID_BLOB_KEY:无法读取blob。

Same with: 与:

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

INVALID_BLOB_KEY: Could not read blob. INVALID_BLOB_KEY:无法读取Blob。

Update - Testing On Live: 更新-实时测试:

I've done some logging on live to see if I can pinpoint where things are going wrong. 我已经进行了一些实时登录,以查看是否可以查明问题出在哪里。

When I print out the GcsFilename, this is what I'm getting: 当我打印出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

Then generating the new blobkey: 然后生成新的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

Then using 3 different methods for getting the new serving urls: 然后使用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...

When I access these URLs, all I'm getting is the original image. 当我访问这些URL时,我得到的只是原始图像。

When I look in the Cloud Storage Dashboard, the original image is sitting in: Home/bucket-name/ 当我在Cloud Storage Dashboard中查看时,原始图像位于:Home / bucket-name /

The rotated image however is sitting in: Home/bucket-name//gs/bucket-name/ 但是旋转后的图像位于:主页/存储桶名称// gs /存储桶名称/

Hence the reason it's not overwriting the original. 因此,它没有覆盖原件的原因。 I'm guessing either the fileName I'm creating is incorrect or the GcsOutputChannel I'm creating is changing the path? 我猜我正在创建的文件名不正确,或者我正在创建的GcsOutputChannel正在更改路径? I'm also curious why I'm getting the original image's url instead of the new image's url? 我也很好奇为什么我要获取原始图像的URL而不是新图像的URL?

If I split the original GcsFileName and only take the last part, I'm getting an error: 如果我分割了原始的GcsFileName并只使用了最后一部分,那我将得到一个错误:

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

Google storage filenames must be prefixed with /gs/ Google存储空间文件名必须以/ gs /作为前缀

Any ideas? 有任何想法吗?

Solution

Retreive blobKey using: 使用以下命令检索blobKey:

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

... even though fileName.getObjectName() already contains "/gs/bucket-name/" in front of the objectname. ...即使fileName.getObjectName()在对象名前面已经包含“ / gs / bucket-name /”。 When printing it to standard out, your fileName should contain /gs/bucket-name/ twice, weird, but it works. 当将其打印为标准输出时,您的fileName应该包含两次/ gs / bucket-name /,这很奇怪,但是可以使用。

Using that blobKey, the correct serving URL is created 使用该blobKey,创建正确的服务网址

To override the original image, you simply need to specify the same Cloud Storage filename. 要覆盖原始映像,您只需要指定相同的Cloud Storage文件名。

I understand that you have uploaded the image to Cloud Storage through App Engine via the BlobStore API. 我们了解您已通过BlobStore API通过App Engine将图像上传到Cloud Storage。 To get the actual filename of the original image, you must add the following code in the upload servlet : 要获取原始图像的实际文件名,必须在上载servlet中添加以下代码

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

Note that if you do not want to overwrite the original file, but want to provide a serving URL to the customer, you can either : 请注意,如果您不想覆盖原始文件,但想向客户提供服务网址,则可以:

  • Use the ImageService like this : 像这样使用ImageService:

     ImagesService imagesService = ImagesServiceFactory.getImagesService(); String url = imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(java)); 
  • Create a custom GCSServingServlet who will use the BlobstoreService.serve() method to serve a file from the Blobstore or Cloud Storage. 创建一个自定义GCSServingServlet ,它将使用BlobstoreService.serve()方法为Blobstore或Cloud Storage中的文件提供服务。 In that case, you must check the permissions yourself. 在这种情况下,您必须自己检查权限。 Note that you can create a BlobKey from a GCSFilename using BlobStoreService.createGSBlobKey() . 请注意,您可以使用BlobStoreService.createGSBlobKey()GCSFilename创建BlobKey

  • Use the Cloud Storage serving URLs : 使用Cloud Storage服务网址:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM