Armazenamento de imagens giradas / invertidas no Google App Engine
Estou tentando girar / inverter uma imagem que já está dentro do Google Cloud Storage.
Este é o blobkey:
BlobKey blobKey = new BlobKey(upload.getBlobKey());
Então, recupero a imagem e aplico uma transformação de imagem:
ImagesService imagesService = ImagesServiceFactory.getImagesService();
Image image = ImagesServiceFactory.makeImageFromBlob(blobKey);
Transform transform = ImagesServiceFactory.makeRotate(90);
Image newImage = imagesService.applyTransform(transform, image);
Os dados de imagem RAW que posso obter em uma matriz de bytes usando:
newImage.getImageData()
Usando o GCS diretamente, posso gravá-lo no serviço de armazenamento em nuvem:
GcsFilename fileName = new GcsFilename("bucket-name", upload.getFileName());
GcsOutputChannel outputChannel = GcsServiceFactory.createGcsService().createOrReplace(fileName, GcsFileOptions.getDefaultInstance());
outputChannel.write(ByteBuffer.wrap(newImage.getImageData()));
outputChannel.close();
Localmente, vejo a imagem girada dentro da pasta gerada pelo aplicativo, como obtenho o novo URL de veiculação ou qual deve ser o nome do objeto para substituir a imagem original? O objectName é igual ao nome do arquivo original quando foi carregado, é o blobkey, ...?
Atualizar:
Estou armazenando o GcsFilename após o upload:
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();
O GcsFileName se parece com este (localmente):
/ gs / bucket-name / fake-encoded_gs_key: YXVjdGlvbi1wb3J0YWwtdXBsb2Fkcy84SXp5VGpIUWlZSDY5X1Ytck5TbGtR-0f969f5b4f53a01479ff2d5eaf02fa1
Em seguida, dentro do meu método de rotação, faço o seguinte:
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());
Quando imprimo o novo blobKey usando bk.getKeyString (), recebo um enorme blobkey:
encoded_gs_key: L2dzL2F1Y3Rpb24tcG9ydGFsLXVwbG9hZHMvZmFrZS1lbmNvZGVkX2dzX2tleTpZWFZqZEdsdmJpMXdiM0owWVd3dGRYQnNiMkZrY3k4NFNYcDVWR3BJVVdsWlNEWTVYMVl0Y2s1VGJHdFItMGY5NjlmNWI0ZjUzYTAxNDc5ZmYyZDVlYWYwMmZhMWE
Quando tento:
imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(bk);
Agora eu recebo umINVALID_BLOB_KEY: Não foi possível ler o blob.
Mesmo com:
imagesService.getServingUrl(ServingUrlOptions.Builder.withGoogleStorageFileName(fileName.getObjectName()));
INVALID_BLOB_KEY: Não foi possível ler o blob.
Atualização - Teste no Live:
Eu fiz alguns logins ao vivo para ver se consigo identificar onde as coisas estão dando errado.
Quando imprimo o GcsFilename, é isso que estou recebendo:
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
Em seguida, gerando o novo 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
Em seguida, use três métodos diferentes para obter os novos URLs de veiculação:
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("new,ImageUrl3: " + 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...
Quando acesso esses URLs, tudo o que recebo é a imagem original.
Quando olho no Cloud Storage Dashboard, a imagem original está em: Página inicial / bucket-name /
A imagem girada, no entanto, está em: Página inicial / bucket-name // gs / bucket-name /
Daí a razão pela qual não está substituindo o original. Acho que o fileName que estou criando está incorreto ou o GcsOutputChannel que estou criando está mudando o caminho? Também estou curioso para saber por que estou recebendo o URL da imagem original em vez do URL da nova imagem?
Se eu dividir o GcsFileName original e apenas participar da última parte, estou recebendo um erro:
GcsFilename fileName = new GcsFilename("bucket-name", upload.getGcsFileName().split("/")[3]);
Os nomes de arquivos de armazenamento do Google devem ser prefixados com / gs /
Alguma ideia?
Solução
Recuperar blobKey usando:
BlobKey blobKey = blobstoreService.createGsBlobKey("/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName());
... embora fileName.getObjectName () já contenha "/ gs / bucket-name /" na frente do nome do objeto. Ao imprimi-lo com o padrão, seu fileName deve conter / gs / bucket-name / duas vezes, estranho, mas funciona.
Usando esse blobKey, o URL de veiculação correto é criado