Estoy usando los siguientes dos JAVA
métodos para crear un archivo firmado URL
para cargarlo en Google Cloud Storage, usando HTTP PUT
. Se supone que el primer método genera la URL de carga real usando POST
, mientras que el segundo se supone que genera el URL
uso serviceAccountCredentials
, que será usado (para POST
) por el primero.
Primer método
public String getUploadLink(String bucketName, String uuid, String objectName, String mimeType)
throws IOException, GenericAttachmentException {
if (!bucketExists(bucketName)) {
createBucket(bucketName);
}
URL myURL = new URL(getSignedUrlToPost(bucketName, uuid, objectName, mimeType));
HttpURLConnection myURLConnection = (HttpURLConnection) myURL.openConnection();
myURLConnection.setRequestMethod("POST");
myURLConnection.setRequestProperty("Content-Type", mimeType);
myURLConnection.setRequestProperty("x-goog-resumable", "start");
// Send POST request
myURLConnection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(myURLConnection.getOutputStream());
wr.flush();
wr.close();
int responseCode = myURLConnection.getResponseCode();
if (responseCode != 201) {
throw new GenericAttachmentException(500,
"Error generating signed URL",
"Something went wrong while attempting to generate the URL.");
}
return myURLConnection.getHeaderField("Location");
}
Segundo método
private String getSignedUrlToPost(String bucketName, String uuid, String objectName,
String mimeType) throws GenericAttachmentException {
try {
String verb = "POST";
long now = System.currentTimeMillis();
/* Expire in a minute. */
long expiryTimeInSeconds = (now + 60 * 1000L) / 1000;
String canonicalizedExtensionHeaders = "x-goog-resumable:start";
byte[] sr = serviceAccountCredentials.sign(
(verb + "\n\n" + mimeType + "\n" + expiryTimeInSeconds + "\n" + canonicalizedExtensionHeaders
+
"\n" + "/" + bucketName + "/" + uuid + "/" + objectName).getBytes());
String urlSignature = new String(Base64.encodeBase64(sr));
return "https://storage.googleapis.com/" + bucketName + "/" + uuid + "/" + objectName +
"?GoogleAccessId=" + serviceAccountEmail +
"&Expires=" + expiryTimeInSeconds +
"&Signature=" + URLEncoder.encode(urlSignature, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new GenericAttachmentException(500,
"Something went wrong while encoding the URL.",
e.getMessage());
}
}
Esto me da una carga URL
, de la siguiente manera:
https://storage.googleapis.com/bucket-name/7c9a5bd6-ece2-497d-b485-a9c53e27f253/a.pdf?GoogleAccessId=storage-dev@project-name-xxxxxx.iam.gserviceaccount.com&Expires=1592883655&Signature=IlTGvwGNN8VYrPE9qzSW0AIAwqMvbNoZ34TQ4nr4Po5vwZx78or9iiqBhO0jqoeoX6BYP%2BHGkWPIKMUijB%2FZ0L6Z%2BtnaZZkIJ581YQ3JK8BEHWqWyf0V07RwAN0TGAyld7h1JntWmGDyXKtjmy6Skt1C0GocJZA2x9GMxo94OD9kpFbjBucixgQDE%2BEtCzDUXWkymATls690pyLftXhAI0CVWg%2FPlcAe2Q%2F9M%2F68s5eWVSXa0%2BXIVQQ%2FucgXO8RbEDeu%2BWjrL3TcYQFTFd8Q%2BvcwKkpjbmKGpmMnYuTc7HSKrRWLLGxixsLBSjKdQDK4Tu14%2F0ROJVJo4Gv%2FX4oknQ%3D%3D&upload_id=AAANsUlwcmdpeCuME5YbeSpnfw5eQw_Sb65xl7t59b6GcNkNE0PUfe44tUDXHfobXRo-EBGI6X-I5zPqXyPBm4paSyBGyzZCWw
Cuestiones:
URL
, pero el enlace no caduca después de un minuto.xyz.jpg
usar HTTP PUT
, regresa 200 OK
, aunque en realidad no carga xyz.jpg
ni reemplaza el archivo original.¿No debería invalidarse el enlace de carga una vez que se usa para cargar algo en el servidor? ¿Me estoy perdiendo de algo? Realmente le vendría bien un poco de ayuda.
Las bibliotecas de Google Cloud para crear una URL firmada son en realidad mucho más simples que crearla "manualmente", como puede ver en el ejemplo de código de muestra en esta documentación oficial . Después de eso, su getSignedUrlToPost
función podría verse así:
private String getSignedUrlToPost(String bucketName, String objectName, String mimeType)
throws StorageException {
try {
Storage storage = StorageOptions.newBuilder().setProjectId("YOUR_PROJECT_ID")
.build().getService();
// Define Resource
BlobInfo blobInfo = BlobInfo.newBuilder(BlobId.of(bucketName, objectName))
.build();
// Generate Signed URL
Map<String, String> extensionHeaders = new HashMap<>();
extensionHeaders.put("Content-Type", mimeType);
//setting it to expire 10 minutes
return storage.signUrl(
blobInfo,
10,
TimeUnit.MINUTES,
Storage.SignUrlOption.httpMethod(HttpMethod.POST),
Storage.SignUrlOption.withExtHeaders(extensionHeaders),
Storage.SignUrlOption.withV4Signature());
} catch (StorageException e) {
throw new StorageException(500,
"Something went wrong while encoding the URL: "
e.getMessage());
}
}
Siempre encuentro que es mejor usar las bibliotecas oficiales, ya que a menudo simplifican su código y es menos propenso a errores, ya que no tiene que averiguar qué se debe hacer detrás de las cortinas.
EDITAR
Para el vencimiento de la URL después de un solo uso, investigué un poco y lo único que pude encontrar es esta pregunta de la comunidad donde la respuesta más votada dice que esto no es posible actualmente.
Aunque es una publicación antigua (más de 5 años), no se menciona que se haya cambiado en la documentación, por lo que supongo que sigue siendo válida. Sugeriría que, para solucionar este problema, haga que la URL tenga un límite de vencimiento de tiempo corto y la ajuste a las necesidades de su aplicación.
NOTA : Puede encontrar más detalles sobre las opciones de las URL firmadas para el almacenamiento en el javadoc para esa clase.
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras