Attachments Uploading as Corrupt Files in Jira - Please help

Andrea34
Tera Contributor

Good afternoon, everyone. I hope you're all doing well.

I'm reaching out to urgently request your help with the following issue: I need to ensure that every attachment uploaded to a change request is successfully transferred to Jira. However, my code is currently sending corrupted files to Jira.

I've tried everything, but I can't figure out what’s causing this. Any guidance or suggestions would be greatly appreciated!

 

 

 

 

BUSINESS RULE 

(function executeRule(current, previous /*null when async*/) {
  gs.info("La Business Rule se está ejecutando. Adjunto: " + current.file_name);

  if (current.table_name.toLowerCase() == "change_request") {
    var changeTaskGR = new GlideRecord("change_request");

    if (changeTaskGR.get(current.table_sys_id)) {
      var jiraIssueId = changeTaskGR.getValue("u_id_hu");

      if (jiraIssueId) {
        gs.info("Jira Issue ID encontrado: " + jiraIssueId);

        // Enviar solo adjuntos nuevos
        sendNewAttachmentsToJira(
          current.table_sys_id,
          jiraIssueId,
          "change_request",
          current.sys_created_on
        );
      } else {
        gs.warn(
          "El campo u_nreferens no tiene valor en la change_task con sys_id: " +
            current.table_sys_id
        );
      }
    } else {
      gs.warn(
        "No se encontró un registro change_task con sys_id: " +
          current.table_sys_id
      );
    }
  }
})(current, previous);

function sendNewAttachmentsToJira(
  sysId,
  jiraIssueId,
  tableName,
  currentCreatedOn
) {
  var attachmentGR = new GlideRecord("sys_attachment");
  attachmentGR.addQuery("table_name", tableName);
  attachmentGR.addQuery("table_sys_id", sysId);
  attachmentGR.addQuery("sys_created_on", ">=", currentCreatedOn); // Solo adjuntos nuevos
	attachmentGR.query();

  while (attachmentGR.next()) {
    var attachmentContent = new GlideSysAttachment().getBytes(attachmentGR);
    var boundary = "----WebKitFormBoundary" + gs.generateGUID();
    var fileName = attachmentGR.file_name;
    var contentType = attachmentGR.content_type;

    var requestBody =
      "--" +
      boundary +
      "\r\n" +
      'Content-Disposition: form-data; name="file"; filename="' +
      fileName +
      '"\r\n' +
      "Content-Type: " +
      contentType +
      "\r\n\r\n" +
      attachmentContent +
      "\r\n" +
      "--" +
      boundary +
      "--";

    var attachmentRequest = new sn_ws.RESTMessageV2();
    attachmentRequest.setHttpMethod("POST");
    attachmentRequest.setEndpoint(
      "https://banreservas-sandbox-149.atlassian.net/rest/api/3/issue/" +
        jiraIssueId +
        "/attachments"
    );

    var base64Auth = GlideStringUtil.base64Encode(
      "user" +
        ":" +
        "token"
    );
    attachmentRequest.setRequestHeader("Authorization", "Basic " + base64Auth);
    attachmentRequest.setRequestHeader("X-Atlassian-Token", "no-check");
    attachmentRequest.setRequestHeader(
      "Content-Type",
      "multipart/form-data; boundary=" + boundary
    );

    attachmentRequest.setRequestBody(requestBody);

    try {
      var attachmentResponse = attachmentRequest.execute();
      var status = attachmentResponse.getStatusCode();
      var responseBody = attachmentResponse.getBody();

      if (status == 200 || status == 201) {
        gs.info(
          'Attachment "' +
            fileName +
            '" subido exitosamente a Jira issue ID: ' +
            jiraIssueId
        );
      } else {
        gs.warn(
          "No se pudo subir el attachment. Status: " +
            status +
            ", Respuesta: " +
            responseBody
        );
      }
    } catch (ex) {
      gs.error("Error al subir el attachment a Jira: " + ex.message);
    }
  }
}

 

 

 

9 REPLIES 9

Hi!

No, the file is being received corrupted in Jira and with a larger size.

Any idea why?

 

This is my code: 

 

 

(function executeRule(current, previous /*null when async*/) {
  gs.info("La Business Rule se está ejecutando. Adjunto: " + current.file_name);

  if (current.table_name.toLowerCase() == "change_request") {
    var changeTaskGR = new GlideRecord("change_request");

    if (changeTaskGR.get(current.table_sys_id)) {
      var jiraIssueId = changeTaskGR.getValue("u_id_hu");

      if (jiraIssueId) {
        gs.info("Jira Issue ID encontrado: " + jiraIssueId);

        // Enviar solo adjuntos nuevos
        sendNewAttachmentsToJira(
          current.table_sys_id,
          jiraIssueId,
          "change_request",
          current.sys_created_on
        );
      } else {
        gs.warn(
          "El campo u_nreferens no tiene valor en la change_task con sys_id: " +
            current.table_sys_id
        );
      }
    } else {
      gs.warn(
        "No se encontró un registro change_task con sys_id: " +
          current.table_sys_id
      );
    }
  }
})(current, previous);

function sendNewAttachmentsToJira(
  sysId,
  jiraIssueId,
  tableName,
  currentCreatedOn
) {
  var attachmentGR = new GlideRecord("sys_attachment");
  attachmentGR.addQuery("table_name", tableName);
  attachmentGR.addQuery("table_sys_id", sysId);
  attachmentGR.addQuery("sys_created_on", ">=", currentCreatedOn); // Solo adjuntos nuevos
  attachmentGR.query();

  while (attachmentGR.next()) {
    var attachmentContent = new GlideSysAttachment().getBytes(attachmentGR);
    gs.info("Size of attachment content: " + attachmentContent.length); // Verifica el tamaño de los bytes

    if (attachmentContent.length == 0) {
      gs.warn("El archivo está vacío, no se enviará.");
      continue; // Si el archivo está vacío, no lo enviamos
    }

    var boundary = "----WebKitFormBoundary" + gs.generateGUID();
    var fileName = attachmentGR.file_name;
    var contentType = attachmentGR.content_type;

    // Construir el cuerpo multipart/form-data manualmente
    var requestBody =
      "--" + boundary + "\r\n" +
      'Content-Disposition: form-data; name="file"; filename="' + fileName + '"\r\n' +
      "Content-Type: " + contentType + "\r\n\r\n";

    // Aseguramos que el contenido binario se agregue directamente sin manipulación innecesaria
    var byteString = String.fromCharCode.apply(null, attachmentContent);

    requestBody += byteString + "\r\n" + 
                   "--" + boundary + "--";

    var attachmentRequest = new sn_ws.RESTMessageV2();
    attachmentRequest.setHttpMethod("POST");
    attachmentRequest.setEndpoint(
      "https://instance.atlassian.net/rest/api/3/issue/" +
      jiraIssueId +
      "/attachments"
    );

    var base64Auth = GlideStringUtil.base64Encode(
      "user" + ":" + "token"
    );
    attachmentRequest.setRequestHeader("Authorization", "Basic " + base64Auth);
    attachmentRequest.setRequestHeader("X-Atlassian-Token", "no-check");
    attachmentRequest.setRequestHeader(
      "Content-Type",
      "multipart/form-data; boundary=" + boundary
    );

    attachmentRequest.setRequestBody(requestBody);

    try {
      var attachmentResponse = attachmentRequest.execute();
      var status = attachmentResponse.getStatusCode();
      var responseBody = attachmentResponse.getBody();

      if (status == 200 || status == 201) {
        gs.info(
          'Attachment "' +
          fileName +
          '" subido exitosamente a Jira issue ID: ' +
          jiraIssueId
        );
      } else {
        gs.warn(
          "No se pudo subir el attachment. Status: " +
          status +
          ", Respuesta: " +
          responseBody
        );
      }
    } catch (ex) {
      gs.error("Error al subir el attachment a Jira: " + ex.message);
    }
  }
}

 

Can you screenshot the error that's being output when the script runs? That would help us narrow down what the issue might be. If the file is arriving larger than it was sent, I wonder if Jira is attempting to decompress a file that was sent uncompressed.



If I've at all helped, please return the favor by clicking the thumb next to my post. Thanks!

Hello! I hope you're doing well.

According to the logs, the file appears to be uploaded successfully, but when I check in Jira, the file size is larger than expected. For example, I’m trying to upload a test file of 128 bytes, but once uploaded, it shows as 172 bytes. The same issue occurs with any other file type, and when I try to download them, they either won’t open or appear empty (e.g., PDFs).

I’ve tried the following solutions without success:

  1. FORM DATA results in a 500 error.
  2. Using Content-Type: application/octet-stream with setRequestBodyFromStream() causes an error.
  3. Jira does not accept binary file uploads without Base64 encoding.
  4. Sending the bytes directly without using String.fromCharCode() still doesn't work.

Any ideas on how to resolve this? 🚀

@Andrea34 

you are sending bytes.

What does JIRA expect? base64 encoded string of attachment?

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
✨ Certified Technical Architect  ||  ✨ 9x ServiceNow MVP  ||  ✨ ServiceNow Community Leader

Hi Ankur 

 

Hope you are doing well. Jira expect pure binary