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

标签 java google-app-engine google-cloud-storage blobstore

我正在尝试旋转/翻转已位于 Google Cloud Storage 中的图像。

这是 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 图像数据:

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-generated 文件夹中,我如何获取新的服务 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 种不同的方法获取新的服务 url:

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 时,我得到的只是原始图像。

当我查看 Cloud Storage 仪表板时,原始图像位于: 主页/桶名/

但是旋转后的图像位于: 主页/桶名//gs/桶名/

这就是它不覆盖原始文件的原因。 我猜是我创建的文件名不正确还是我创建的 GcsOutputChannel 正在更改路径? 我也很好奇为什么我得到的是原始图片的 url 而不是新图片的 url?

如果我拆分原始 GcsFileName 并只取最后一部分,我会收到错误消息:

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

Google 存储文件名必须以/gs/为前缀

有什么想法吗?

解决方案

检索 blobKey 使用:

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

... 即使 fileName.getObjectName() 已在对象名称前面包含“/gs/bucket-name/”。将其打印到标准输出时,您的文件名应该包含/gs/bucket-name/两次,这很奇怪,但它有效。

使用该 blobKey,创建正确的服务 URL

最佳答案

要覆盖原始图像,您只需指定相同的云存储文件名即可。

我了解到您已通过 App Engine 通过 BlobStore API 将图像上传到 Cloud Storage。要获取原始图像的实际文件名,您必须在上传 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 或 Cloud Storage 提供文件。在这种情况下,您必须自己检查权限。请注意,您可以使用 BlobStoreService.createGSBlobKey()GCSFilename 创建一个 BlobKey

  • 使用云存储服务 URL:

关于java - 在 Google App Engine 中存储旋转/翻转图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22128693/

相关文章:

java - 比较 2 个 URL 是否具有相同的原始目标

java - 根据预定义的规则集将输入集分类为类别

Java:比较字符串

python - 谷歌应用引擎: LinkProperty to string

java - 如何将 JavaScript 数组转换为 Java 数组

python - 在 Python 2.5 中将 Google App Engine blobstore 作为文件写入的正确方法是什么

python - client.get_bucket() 失败,但仅来自云数据流(计算引擎)

python - 如何在 Python 中列出 Google Cloud Bucket 文件夹中的所有对象?

java - Google 云存储 - 监控文件更改

python - Google Bigquery 某些内容返回空/无行