Subir un objeto con formularios de HTML

Sube objetos mediante formularios HTML. El objeto subido reemplaza cualquier objeto existente con el mismo nombre. Para obtener sugerencias sobre cómo subir a Cloud Storage, consulta las prácticas recomendadas.

Para obtener información sobre las solicitudes de objetos POST mediante el proceso de firma heredado, consulta Objeto POST con el proceso de firma de V2.

Parámetros de string de consulta

Esta solicitud no incluye parámetros de cadena de consulta.

Campos del formulario

Campo Descripción Obligatorio
acl La LCA predefinida que deseas aplicar al objeto que se está subiendo. Si no especificas este campo, se aplica la LCA del default del depósito. No
bucket El nombre del depósito al que deseas subir el archivo. Si incluyes este campo, debe coincidir con el nombre del depósito que especifiques en el atributo action. No
Cache-Control El control de caché del objeto. Solo puedes configurar el control de caché para un objeto al que pueda acceder todos los usuarios. Por ejemplo, la LCA de un objeto debe ser public-read o public-read-write para poder configurar el control de caché. No
Content-Disposition Especifica cómo se deben transmitir los datos del objeto. Por ejemplo, un valor Content-Disposition de inline significa que el objeto debe mostrarse de inmediato. No
Content-Encoding El algoritmo de compresión para el objeto, como gzip. No
Content-Length El tamaño del archivo que se subió, en bytes. No
Content-Type El tipo de MIME del archivo que estás subiendo mediante el formulario. Si no especificas un tipo de contenido, el sistema de Cloud Storage usa de forma predeterminada application/octet-stream cuando entrega el contenido. No
Expires Una marca de tiempo ISO8601 que especifica la fecha y hora antes de que el navegador considera inactiva un objeto. No
file El archivo que estás subiendo. Debe ser el último campo del formulario. Solo puedes subir un objeto por solicitud.
key El nombre del objeto que deseas subir. También puedes usar la variable ${filename} si un usuario proporciona un nombre de archivo.
policy

La política de seguridad que describe lo que puede y no se puede subir en el formulario. El documento de políticas debe estar codificado en Base64. Consulta los documentos de las políticas para obtener más información.

*Si no proporcionas una política de seguridad, se considera que las solicitudes son anónimas y solo funcionarán con depósitos que tengan permiso WRITE o FULL_CONTROL para usuarios anónimos.

No*
success_action_redirect URL a la que se redirige a los usuarios cuando una carga se realiza correctamente Si no proporcionas una URL, Cloud Storage responde con el código de estado que especificaste en success_action_status. No
success_action_status El código de estado con el que quieres que responda Cloud Storage cuando se completa una carga. El valor predeterminado es 204, pero puedes cambiarlo en 200 o 201. Si eliges 200 o 204, Cloud Storage muestra un documento vacío con esos códigos de estado. Si eliges 201, Cloud Storage muestra un documento XML con los elementos que se describen en los elementos del cuerpo de la respuesta. Nota: Es posible que el reproductor Adobe Flash no maneje las respuestas con un cuerpo de documento vacío. En ese caso, debes usar el código de estado 201. No
x-goog-algorithm El algoritmo de firma usado para crear la firma asociada con tu documento de políticas. Los valores posibles son GOOG4-HMAC-SHA256 y GOOG4-RSA-SHA256. Solo si especificas un policy
x-goog-credential Las credenciales que se usan para crear la firma asociada con tu documento de política. x-goog-credential tiene el formato AccessKeyId/CredentialScope, donde:
  • AccessKeyId es la dirección de correo electrónico de la entidad responsable de crear la firma. Por lo general, esta entidad es una cuenta de servicio, pero también puede ser una cuenta de usuario.
  • CredentialScope es el alcance de credencial que se usa en la firma.
Solo si especificas un policy
x-goog-custom-time Una fecha y hora especificadas por el usuario en el formato YYYY-MM-DD'T'HH:MM:SS.SS'Z' RFC 3339 No
x-goog-date La fecha actual, en el formato básico de ISO 8601 YYYYMMDD'T'HHMMSS'Z' Solo si especificas un policy
x-goog-signature La firma asociada con tu documento de política. Solo si especificas un policy
x-goog-meta-* Un campo para los metadatos personalizados. Puedes usarlo para especificar los metadatos adicionales que no proporcionen los otros campos del formulario. Por ejemplo, x-goog-meta-reviewer: jane o x-goog-meta-project-manager: john son metadatos personalizados. No

Elementos del cuerpo de la respuesta

Los siguientes elementos del cuerpo de respuesta se muestran en un documento XML solo si configuras success_action_status como 201.

Elemento Descripción
Bucket Depósito en el que se almacenó el objeto
ETag La etiqueta de entidad HTTP 1.1 para el objeto.
Key El nombre del objeto.
Location El URI del objeto.

Uso y ejemplos

El formulario debe estar codificado en UTF-8. Puedes especificar la codificación de formulario en la etiqueta HTML head del formulario o con el encabezado de solicitud Content-Type.

Tu etiqueta form debe especificar los siguientes tres elementos:

  • Una acción

    El atributo action especifica un extremo de solicitud de la API de XML. Los extremos válidos incluyen los redireccionamientos https://BUCKET_NAME.storage.googleapis.com, https://storage.googleapis.com/BUCKET_NAME y CNAME.

  • Un método.

    El atributo method especifica el método que usas para enviar el formulario. Debe ser post.

  • Un tipo de soporte.

    El atributo enctype especifica el tipo de contenido que usas y siempre debe ser multipart/form-data.

El siguiente es un formulario HTML de ejemplo con un documento de política:

HTML

<form action="https://storage.googleapis.com/travel-maps" method="post" enctype="multipart/form-data">
<input type="text" name="key" value="test-object">
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="hidden" name="success_action_redirect" value="https://www.example.com/success_notification.html">
<input type="hidden" name="policy" value="eyJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJ0cmF2ZWwtbWFwcyJ9LHsiY29udGVudC10eXBlIjoiaW1hZ2UvanBlZyJ9LHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiJodHRwOi8vd3d3LmV4YW1wbGUuY29tL3N1Y2Nlc3Nfbm90aWZpY2F0aW9uLmh0bWwifSx7ImtleSI6InRlc3Qtb2JqZWN0In0seyJ4LWdvb2ctZGF0ZSI6IjIwMjAwMTIzVDA0MzUzMFoifSx7IngtZ29vZy1jcmVkZW50aWFsIjoiZXhhbXBsZV9hY2NvdW50QGV4YW1wbGVfcHJvamVjdC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbS8yMDE5MTEwMi9hdXRvL3N0b3JhZ2UvZ29vZzRfcmVxdWVzdCJ9LHsieC1nb29nLWFsZ29yaXRobSI6IkdPT0c0LVJTQS1TSEEyNTYifV0sImV4cGlyYXRpb24iOiIyMDIwLTAxLTIzVDA0OjM1OjQwWiJ9">
<input type="hidden" name="x-goog-algorithm" value="GOOG4-RSA-SHA256">
<input type="hidden" name="x-goog-credential" value="example_account@example_project.iam.gserviceaccount.com/20191102/auto/storage/goog4_request">
<input type="hidden" name="x-goog-date" value="20191102T043530Z">
<input type="hidden" name="x-goog-signature" value="58bc39b8f604ee1f18171fee4828ef8967f3d2721676570e115d68c2f133820cbb833976f18955516b2b7d0c3d9660fea613a2ad90c240bd02c1eefa4a55e9038ce74dcfdd34e278ea0436e261131a36fa4e922f0a077ca1c9842f654928aac3ca7f9341075f9db275d8286b5ef13e7f91b4837e77b2a6dbea83f86b90f848331053d8a6b1fbc26787992e7fb819a2005bae9b3026b9c7d1158e88e4a2018f13757083c7873241d2dfe6ea46a17cd6f3d090f3e0da44ccfbd6bc425124de1bea744a32f3ab175672a991ef274cd83550eca57ea591b85fa9799098a38ec552dc3ec679c431491444820624f5c4ba0c8cf87d60af89899afce2a90325c6966dcf">

<input name="file" type="file">
<input type="submit" value="Upload">
</form>

C++

C++

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para C++.

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& object_name, std::string const& signing_account) {
  auto document = client.GenerateSignedPostPolicyV4(
      gcs::PolicyDocumentV4{
          bucket_name,
          object_name,
          /*expiration=*/std::chrono::minutes(10),
      },
      gcs::AddExtensionFieldOption("x-goog-meta-test", "data"),
      gcs::SigningAccount(signing_account));
  if (!document) throw std::runtime_error(document.status().message());

  // Create the HTML form for the computed policy.
  std::ostringstream os;
  os << "<form action='" << document->url << "' method='POST'"
     << " enctype='multipart/form-data'>\n";
  for (auto const& field : document->required_form_fields) {
    os << "  <input name='" << field.first << "' value='" << field.second
       << "' type='hidden' />\n";
  }
  os << "  <input type='submit' value='Upload File' /><br />\n"
     << "  <input type='file' name='file' /><br />\n"
     << "</form>";

  std::cout << "A sample HTML form:\n" << os.str() << "\n";
}

C#

C#

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para C#.

// Create a signed post policy which can be used to upload a specific object and
// expires in 1 hour after creation.
UrlSigner urlSigner = UrlSigner
    .FromServiceAccountCredential(credential);
UrlSigner.Options options = UrlSigner.Options
    .FromDuration(TimeSpan.FromHours(1))
    .WithSigningVersion(SigningVersion.V4)
    .WithScheme("https");
UrlSigner.PostPolicy postPolicy = UrlSigner.PostPolicy.ForBucketAndKey(bucketName, objectName);
postPolicy.SetCustomField(UrlSigner.PostPolicyCustomElement.GoogleMetadata, "x-goog-meta-test", "data");

UrlSigner.SignedPostPolicy signedPostPolicy = await urlSigner.SignAsync(postPolicy, options);

// Create an HTML form including all the fields in the signed post policy.
StringBuilder form = new StringBuilder();
form.AppendLine($"<form action=\"{signedPostPolicy.PostUrl}\" method=\"post\" enctype=\"multipart/form-data\">");
foreach (var field in signedPostPolicy.Fields)
{
    form.AppendLine($"<input type=\"hidden\" name=\"{field.Key}\" value=\"{field.Value}\">");
}
// Include the file element. It should always be the last element in the form.
form.AppendLine("<input name=\"file\" type=\"file\">");
form.AppendLine("<input type=\"submit\" value=\"Upload\">");
form.AppendLine("</form>");

// You can now save the form to file and serve it as static content
// or send it as the response to a request made to your application.
File.WriteAllText("PostPolicySimple.html", form.ToString());

Java

Java

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para Java.

import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.PostPolicyV4;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class GenerateSignedPostPolicyV4 {
  /**
   * Generating a signed POST policy requires Credentials which implement ServiceAccountSigner.
   * These can be set explicitly using the Storage.PostPolicyV4Option.signWith(ServiceAccountSigner)
   * option. If you don't, you could also pass a service account signer to StorageOptions, i.e.
   * StorageOptions().newBuilder().setCredentials(ServiceAccountSignerCredentials). In this example,
   * neither of these options are used, which means the following code only works when the
   * credentials are defined via the environment variable GOOGLE_APPLICATION_CREDENTIALS, and those
   * credentials are authorized to sign a policy. See the documentation for
   * Storage.generateSignedPostPolicyV4 for more details.
   */
  public static void generateSignedPostPolicyV4(
      String projectId, String bucketName, String blobName) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of the GCS bucket to upload to
    // String bucketName = "your-bucket-name"

    // The name to give the object uploaded to GCS
    // String blobName = "your-object-name"

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();

    PostPolicyV4.PostFieldsV4 fields =
        PostPolicyV4.PostFieldsV4.newBuilder().AddCustomMetadataField("test", "data").build();

    PostPolicyV4 policy =
        storage.generateSignedPostPolicyV4(
            BlobInfo.newBuilder(bucketName, blobName).build(), 10, TimeUnit.MINUTES, fields);

    StringBuilder htmlForm =
        new StringBuilder(
            "<form action='"
                + policy.getUrl()
                + "' method='POST' enctype='multipart/form-data'>\n");
    for (Map.Entry<String, String> entry : policy.getFields().entrySet()) {
      htmlForm.append(
          "  <input name='"
              + entry.getKey()
              + "' value='"
              + entry.getValue()
              + "' type='hidden' />\n");
    }
    htmlForm.append("  <input type='file' name='file'/><br />\n");
    htmlForm.append("  <input type='submit' value='Upload File'/><br />\n");
    htmlForm.append("</form>\n");

    System.out.println(
        "You can use the following HTML form to upload an object to bucket "
            + bucketName
            + " for the next ten minutes:");
    System.out.println(htmlForm.toString());
  }
}

Comienza a usarlo

Comienza a usarlo

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para Go.

import (
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"time"

	"cloud.google.com/go/storage"
	"golang.org/x/oauth2/google"
)

// form is a template for an HTML form that will use the data from the signed
// post policy.
var form = `<form action="{{ .URL }}" method="POST" enctype="multipart/form-data">
	{{- range $name, $value := .Fields }}
	<input name="{{ $name }}" value="{{ $value }}" type="hidden"/>
	{{- end }}
	<input type="file" name="file"/><br />
	<input type="submit" value="Upload File" name="submit"/><br />
</form>`

var tmpl = template.Must(template.New("policyV4").Parse(form))

// generateSignedPostPolicyV4 generates a signed post policy.
func generateSignedPostPolicyV4(w io.Writer, bucket, object, serviceAccountJSONPath string) (*storage.PostPolicyV4, error) {
	// bucket := "bucket-name"
	// object := "object-name"
	// serviceAccountJSONPath := "service_account.json"
	jsonKey, err := ioutil.ReadFile(serviceAccountJSONPath)
	if err != nil {
		return nil, fmt.Errorf("ioutil.ReadFile: %v", err)
	}
	conf, err := google.JWTConfigFromJSON(jsonKey)
	if err != nil {
		return nil, fmt.Errorf("google.JWTConfigFromJSON: %v", err)
	}
	metadata := map[string]string{
		"x-goog-meta-test": "data",
	}
	opts := &storage.PostPolicyV4Options{
		GoogleAccessID: conf.Email,
		PrivateKey:     conf.PrivateKey,
		Expires:        time.Now().Add(10 * time.Minute),
		Fields: &storage.PolicyV4Fields{
			Metadata: metadata,
		},
	}

	policy, err := storage.GenerateSignedPostPolicyV4(bucket, object, opts)
	if err != nil {
		return nil, fmt.Errorf("storage.GenerateSignedPostPolicyV4: %v", err)
	}

	// Generate the form, using the data from the policy.
	if err = tmpl.Execute(w, policy); err != nil {
		return policy, fmt.Errorf("executing template: %v", err)
	}

	return policy, nil
}

Node.js

Node.js

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para Node.js.

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

// The ID of your GCS file
// const fileName = 'your-file-name';

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

async function generateV4SignedPolicy() {
  const bucket = storage.bucket(bucketName);
  const file = bucket.file(fileName);

  // These options will allow temporary uploading of a file
  // through an HTML form.
  const expires = Date.now() + 10 * 60 * 1000; //  10 minutes
  const options = {
    expires,
    fields: {'x-goog-meta-test': 'data'},
  };

  // Get a v4 signed policy for uploading file
  const [response] = await file.generateSignedPostPolicyV4(options);

  // Create an HTML form with the provided policy
  let output = `<form action='${response.url}' method='POST' enctype="multipart/form-data">\n`;
  // Include all fields returned in the HTML form as they're required
  for (const name of Object.keys(response.fields)) {
    const value = response.fields[name];
    output += `  <input name='${name}' value='${value}' type='hidden'/>\n`;
  }
  output += "  <input type='file' name='file'/><br />\n";
  output +=
    "  <input type='submit' value='Upload File' name='submit'/><br />\n";
  output += '</form>';

  console.log(output);
}

generateV4SignedPolicy().catch(console.error);

PHP

PHP

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para PHP.

use Google\Cloud\Storage\StorageClient;

/**
 * Generates a V4 POST Policy to be used in an HTML form and echo's form.
 *
 * @param string $bucketName the name of your Google Cloud bucket.
 * @param string $objectName the name of your Google Cloud object.
 *
 * @return void
 */
function generate_v4_post_policy($bucketName, $objectName)
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);

    $response = $bucket->generateSignedPostPolicyV4(
        $objectName,
        new \DateTime('10 min'),
        [
            'fields' => [
                'x-goog-meta-test' => 'data'
            ]
        ]
    );

    $url = $response['url'];
    $output = "<form action='$url' method='POST' enctype='multipart/form-data'>" . PHP_EOL;
    foreach ($response['fields'] as $name => $value) {
        $output .= "  <input name='$name' value='$value' type='hidden'/>" . PHP_EOL;
    }
    $output .= "  <input type='file' name='file'/><br />" . PHP_EOL;
    $output .= "  <input type='submit' value='Upload File' name='submit'/><br />" . PHP_EOL;
    $output .= "</form>" . PHP_EOL;

    echo $output;
}

Python

Python

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para Python.

import datetime

from google.cloud import storage

def generate_signed_post_policy_v4(bucket_name, blob_name):
    """Generates a v4 POST Policy and prints an HTML form."""
    # bucket_name = 'your-bucket-name'
    # blob_name = 'your-object-name'

    storage_client = storage.Client()

    policy = storage_client.generate_signed_post_policy_v4(
        bucket_name,
        blob_name,
        expiration=datetime.timedelta(minutes=10),
        fields={
          'x-goog-meta-test': 'data'
        }
    )

    # Create an HTML form with the provided policy
    header = "<form action='{}' method='POST' enctype='multipart/form-data'>\n"
    form = header.format(policy["url"])

    # Include all fields returned in the HTML form as they're required
    for key, value in policy["fields"].items():
        form += "  <input name='{}' value='{}' type='hidden'/>\n".format(key, value)

    form += "  <input type='file' name='file'/><br />\n"
    form += "  <input type='submit' value='Upload File' /><br />\n"
    form += "</form>"

    print(form)

    return form

Ruby

Ruby

Si deseas obtener más información, consulta la documentación de referencia de la API de Cloud Storage para Ruby.

def generate_signed_post_policy_v4 bucket_name:, file_name:
  # The ID of the GCS bucket to upload to
  # bucket_name = "your-unique-bucket-name"

  # The name to give the object uploaded to GCS
  # file_name = "your-file-name"

  require "google/cloud/storage"

  storage = Google::Cloud::Storage.new

  bucket = storage.bucket bucket_name
  post_object = bucket.generate_signed_post_policy_v4 file_name,
                                                      expires: 600,
                                                      fields:  { "x-goog-meta-test" => "data" }

  html_form = "<form action='#{post_object.url}' method='POST' enctype='multipart/form-data'>\n"
  post_object.fields.each do |name, value|
    html_form += "  <input name='#{name}' value='#{value}' type='hidden'/>\n"
  end
  html_form += "  <input type='file' name='file'/><br />\n"
  html_form += "  <input type='submit' value='Upload File'/><br />\n"
  html_form += "</form>\n"

  puts "You can use the following form to upload an object to bucket #{bucket_name} for the next 10 minutes:\n"
  puts html_form

  post_object
end

Como práctica recomendada, debes usar el encabezado Expect: 100-continue con solicitudes POST. Esto te permite verificar que el servidor maneje la solicitud antes de enviar el objeto. Si recibes un código de estado 100 Continue, debes continuar con la solicitud. Si recibes un código de estado 417 Expectation Failed, no debes enviar el objeto.