Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latest File Upload API showing pdf file as binary file in slack preview #2170

Closed
HarishContinube opened this issue Mar 10, 2025 · 5 comments
Closed
Labels
pkg:web-api applies to `@slack/web-api` question M-T: User needs support to use the project

Comments

@HarishContinube
Copy link

I have integrated the latest file upload APIs in Golang. I am trying to upload a PDF file to Slack. The file is uploaded successfully but appears as a binary file in the Slack preview. However, once downloaded, it is in the correct PDF format. The filetype and mimetype values extracted from the completeExternalUrl response seem inconsistent.

Do I need to pass the filetype in any of the three API calls?

Is there any documentation for the second API call used to upload the file after the getUploadURLExternal API?

@zimeg zimeg added question M-T: User needs support to use the project and removed untriaged labels Mar 11, 2025
@zimeg
Copy link
Member

zimeg commented Mar 11, 2025

Hey @HarishContinube! 👋 It's exciting to hear of file uploads in Go, thanks for writing in 🤓

Uploading files using the files.getUploadURLExternal and files.completeUploadExternal Slack API methods - instead of the latest filesUploadV2 method - can be done according to this reference 📚 ✨

Uploading a PDF file should be similar to other files, and I'm finding a preview is appearing with the following Node.js snippet:

import fs from "fs";
import webapi from "@slack/web-api";

const filepath = "example.pdf";
const length = 25469;

const client = new webapi.WebClient(process.env.SLACK_BOT_TOKEN);

const url = await client.files.getUploadURLExternal({
  filename: filepath,
  length,
});

const _upload = await fetch(url.upload_url, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}`
  },
  body: fs.readFileSync(filepath)
});

const _complete = await client.files.completeUploadExternal({
  channel_id: process.env.SLACK_CHANNEL_ID,
  files: [{ id: url.file_id }],
});

In this example, I think it's important that the filename used for the files.getUploadURLExternal method ends with ".pdf", though I'm not certain if this guarantees a PDF preview...

It might also be possible that the POST request is still be processed asynchronously when the file is posted to a channel 🤔

If possible, can you share an example file, code snippet, or details about the file? I'm curious if large files might be the cause of this behavior!

@zimeg
Copy link
Member

zimeg commented Mar 11, 2025

📝 For organizing purposes, I'm moving this issue to slackapi/node-slack-sdk where the filesUploadV2 implementation is!

@zimeg zimeg transferred this issue from slackapi/bolt-js Mar 11, 2025
@zimeg zimeg added the pkg:web-api applies to `@slack/web-api` label Mar 11, 2025
@HarishContinube HarishContinube marked this as a duplicate of slackapi/bolt-js#2454 Mar 11, 2025
@HarishContinube
Copy link
Author

Hi @zimeg. Thanks for your response.

In the last step, files.completeExternalUrl, since the process is asynchronous, I receive the next response from the bot before the file is attached. Is there a way to wait until the file is attached to Slack before proceeding with the next message in the bot?"

@zimeg
Copy link
Member

zimeg commented Mar 12, 2025

@HarishContinube Of course!

Is there a way to wait until the file is attached to Slack before proceeding with the next message in the bot?

You're finding an edge in the asynchronous nature with files uploads... While the file ID and permalink might be available, certain details about the file such as mimetype might not be known immediately after the files.completeExternalUrl call completes 📚

Continuing with the above example, I would recommend checking the files.info response for a value that signals a completed upload with something like:

async function filesInfoMimetypeBackoff(id) {
  for (let i = 1; i < 30; i *= 2) {
    const info = await client.files.info({
      file: id,
    });
    if (info.file.mimetype) {
      return info;
    } else {
      console.log("waiting...");
    }
    await wait(i * 1000);
  }
}

function wait(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

const _info = await filesInfoMimetypeBackoff(url.file_id);

When testing this and a file with length 1406027 I was finding a second or two delay was enough to return the file info and a mimetype! 👾

I'm hoping this is helpful for retrieving file info, but please let me know if you have other questions 🙏 ✨

@HarishContinube
Copy link
Author

It works fine. Thanks for your response @zimeg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg:web-api applies to `@slack/web-api` question M-T: User needs support to use the project
Projects
None yet
Development

No branches or pull requests

2 participants