Saltar al contenido principal

Adjuntar un archivo a un registro desde un script

Objetivo​

Permitir que alguien externo (un portal, el sistema de un socio) adjunte un archivo a un registro a través de una API personalizada, de modo que sea su script quien decida en qué registro acaba y si quien llama puede hacerlo.

Por qué existe​

Las columnas Archivo e Imagen de un registro ya tienen sus propios puntos de conexión, y un formulario los usa. Un portal no puede: un portal se comunica con la plataforma a través de API personalizadas y nada más, porque la comprobación que impide que un cliente llegue a los registros de otro tiene que estar en un script junto a portalCustomerId(), no en el generador de solicitudes de un sitio web.

Así que ahora un script puede guardar un archivo en el campo de un registro y volver a leerlo. Los bytes viajan como texto base64, porque un script no tiene otra manera de contenerlos: quien llama codifica, la plataforma descodifica y el script se limita a pasar la cadena.

Qué puede hacer un script​

putRecordFile(table, id, field, fileName, contentType, contentBase64)Guarda el archivo en el campo del registro. Devuelve true, o false si no pudo
getRecordFile(table, id, field)El archivo como objeto (fileName, contentType, sizeBytes, contentBase64), o nada si el campo está vacío

Ambas actúan en nombre de quien llama: guardar requiere permiso de actualización sobre el registro y leer requiere permiso de lectura, exactamente igual que los puntos de conexión de archivos del propio registro. El límite de tamaño del campo y la regla de solo imágenes son de la plataforma, no del script.

Pasos​

  1. Dé a la tabla una columna Archivo (par_attachment) y, si una lista debe mostrar el nombre sin obtener el archivo, una columna Texto junto a ella para el nombre.

  2. En el esquema de solicitud de la API personalizada, reciba el archivo como tres propiedades:

    "attachmentName": { "type": "string", "maxLength": 260 },
    "attachmentType": { "type": "string", "maxLength": 200 },
    "attachmentBase64": { "type": "string", "maxLength": 5600000 }

    O, desde la ronda 10 de portales, como un único objeto, que es lo que envía el selector de archivos de una pantalla dibujada y la forma con la que responde getRecordFile:

    "par_document": {
    "type": "object",
    "additionalProperties": false,
    "required": ["fileName", "contentType", "contentBase64"],
    "properties": {
    "fileName": { "type": "string", "maxLength": 260 },
    "contentType": { "type": "string", "maxLength": 200 },
    "sizeBytes": { "type": "integer" },
    "contentBase64": { "type": "string", "maxLength": 5600000 }
    }
    }

    Entonces getInput('par_document') entrega el objeto completo al script, y file.fileName lee uno de sus miembros. Si quien llama es una pantalla de un portal de Parsware, use esta forma; consulte Permitir que los visitantes adjunten un archivo.

  3. En el script, cree primero el registro y después el archivo (un archivo de registro pertenece a un registro):

    var id = createRecord('par_request', {
    par_name: getInput('subject'),
    par_attachment_name: getInput('attachmentName')
    });
    if (!isEmpty(getInput('attachmentBase64'))) {
    putRecordFile('par_request', id, 'par_attachment',
    getInput('attachmentName'), getInput('attachmentType'), getInput('attachmentBase64'));
    }
  4. Para devolver un archivo, compruebe primero que el registro es de quien llama y después léalo:

    var file = getRecordFile('par_request', id, 'par_attachment');
    if (isEmpty(file)) {
    setStatus(404);
    } else {
    setOutput('fileName', file.fileName);
    setOutput('contentType', file.contentType);
    setOutput('contentBase64', file.contentBase64);
    }

Tres cosas que suelen pillar a la gente​

  • Compruebe la propiedad antes de leer. getRecordFile se ejecuta en nombre de la aplicación que llama, que perfectamente puede tener permiso para leer todos los registros de la tabla. La pregunta «¿este registro es de quien llama?» le corresponde a su script, y se responde leyendo el registro y comparando.
  • El nombre de la fila es una instantánea. La fila del archivo conserva el nombre real; una columna de texto junto a ella permite que una lista muestre «📎 report.pdf» sin una llamada de archivo por fila. Escríbalo cuando guarde el archivo, y seguirá siendo correcto hasta que alguien sustituya el archivo por otra vía.
  • Los archivos grandes no pasan por un script. Un archivo que supera el límite del campo se guarda en Object Storage y lo transmite por secuencias el punto de conexión del registro; getRecordFile lo rechaza en lugar de cargar cientos de megabytes dentro de un intérprete.

Confirmar que ha funcionado​

Abra el registro en su aplicación: la columna de archivo muestra el archivo, y al descargarlo se obtiene lo que envió quien llama. El historial de auditoría registra el cambio con el nombre y el hash del archivo.

Solución de problemas​

«espera el contenido del archivo como texto base64; lo que se pasó no se puede descodificar». Quien llama envió los bytes sin codificar, o una URL de datos que todavía lleva su prefijo data:…;base64,. Envíe solo el base64.

«El archivo tiene N bytes; el límite de este campo es M bytes». Supera el límite y no hay ningún Object Storage configurado al que derivarlo. Pida a quien llama algo más pequeño o configure un bucket de desbordamiento.

«no puede contener un archivo de N bytes; un script lee archivos de hasta M bytes». El archivo se derivó a Object Storage. Sírvalo a través del punto de conexión de archivos del registro, que lo transmite por secuencias.