# File Operations

Upload files, manage file permissions, and interact with Slack's file storage system.

## Capabilities

### File Upload V2 (Recommended)

Modern file upload implementation using Slack's external upload flow for better performance and reliability.

```typescript { .api }
/**
 * Upload files using the v2 external upload method
 * @param options - File upload configuration
 * @returns Promise resolving to upload results with file details
 */
files.uploadV2(options: FilesUploadV2Arguments): Promise<WebAPICallResult & {
  files: FilesCompleteUploadExternalResponse[];
}>;

interface FilesUploadV2Arguments {
  /** Channel ID where the file will be shared */
  channel_id?: string;
  /** Channel names where the file will be shared (comma-separated) */
  channels?: string;
  /** Title of the file */
  title?: string;
  /** File content as Buffer, Stream, or string */
  file?: Buffer | NodeJS.ReadableStream | string;
  /** Filename for the uploaded file */
  filename?: string;
  /** File type/extension */
  filetype?: string;
  /** Alternative file content (for text files) */
  content?: string;
  /** Initial comment to add with the file */
  initial_comment?: string;
  /** Thread timestamp to upload file to a specific thread */
  thread_ts?: string;
  /** Alt text for accessibility */
  alt_text?: string;
  /** Snippet type for code files */
  snippet_type?: string;
}
```

**Usage Examples:**

```typescript
import { WebClient } from "@slack/web-api";
import { createReadStream } from "fs";

const web = new WebClient(token);

// Upload file from filesystem
const result = await web.files.uploadV2({
  channels: '#general',
  file: createReadStream('./report.pdf'),
  filename: 'monthly-report.pdf',
  title: 'Monthly Sales Report',
  initial_comment: 'Here is this month\'s sales report with key metrics.'
});

console.log('Uploaded files:', result.files.map(f => f.id));

// Upload text content as a file
await web.files.uploadV2({
  channels: 'D1234567890', // Direct message
  content: JSON.stringify({ data: 'example' }, null, 2),
  filename: 'data.json',
  filetype: 'json',
  title: 'Sample Data'
});

// Upload to specific thread with alt text
await web.files.uploadV2({
  channel_id: 'C1234567890',
  file: Buffer.from('Debug info:\n\nError occurred at line 42'),
  filename: 'debug.log',
  thread_ts: '1234567890.123456',
  alt_text: 'Debug log file showing error details'
});

// Upload code snippet
await web.files.uploadV2({
  channels: '#dev-team',
  content: `
function greet(name) {
  return \`Hello, \${name}!\`;
}
  `.trim(),
  filename: 'greeting.js',
  snippet_type: 'javascript',
  title: 'Greeting Function'
});
```

### File Information

Retrieve detailed information about uploaded files.

```typescript { .api }
/**
 * Get information about a file
 * @param options - File info parameters
 * @returns Promise resolving to file details
 */
files.info(options: FilesInfoArguments): Promise<FilesInfoResponse>;

interface FilesInfoArguments {
  /** File ID to get info about */
  file: string;
  /** Number of items to return per page for comments */
  count?: number;
  /** Page number of comments to return */
  page?: number;
}
```

**Usage Examples:**

```typescript
// Get basic file information
const fileInfo = await web.files.info({
  file: 'F1234567890'
});

console.log('File name:', fileInfo.file.name);
console.log('File size:', fileInfo.file.size, 'bytes');
console.log('File type:', fileInfo.file.pretty_type);
console.log('Created by:', fileInfo.file.user);

// Get file info with comments
const fileWithComments = await web.files.info({
  file: 'F1234567890',
  count: 50,
  page: 1
});

console.log('Comments:', fileWithComments.comments);
```

### List Files

Retrieve lists of files with filtering and pagination.

```typescript { .api }
/**
 * List files uploaded to the workspace
 * @param options - List parameters
 * @returns Promise resolving to files list
 */
files.list(options?: FilesListArguments): Promise<FilesListResponse>;

interface FilesListArguments {
  /** Filter files by user ID */
  user?: string;
  /** Filter files by channel ID */
  channel?: string;
  /** Filter by file type (e.g., 'images', 'pdfs', 'zips') */
  types?: string;
  /** End of time range of files to include */
  ts_to?: number;
  /** Start of time range of files to include */
  ts_from?: number;
  /** Number of items to return per page */
  count?: number;
  /** Page number to return */
  page?: number;
  /** Show files hidden by limit */
  show_files_hidden_by_limit?: boolean;
}
```

**Usage Examples:**

```typescript
// List recent files
const recentFiles = await web.files.list({
  count: 20,
  page: 1
});

console.log(`Found ${recentFiles.files.length} files`);

// List files by specific user
const userFiles = await web.files.list({
  user: 'U1234567890',
  count: 50
});

// List files in specific channel
const channelFiles = await web.files.list({
  channel: 'C1234567890',
  count: 100
});

// List files by type and date range
const lastWeek = Math.floor((Date.now() - 7 * 24 * 60 * 60 * 1000) / 1000);
const imageFiles = await web.files.list({
  types: 'images',
  ts_from: lastWeek,
  count: 30
});
```

### Delete Files

Remove files from the workspace.

```typescript { .api }
/**
 * Delete a file
 * @param options - Delete parameters
 * @returns Promise resolving to deletion confirmation
 */
files.delete(options: FilesDeleteArguments): Promise<FilesDeleteResponse>;

interface FilesDeleteArguments {
  /** File ID to delete */
  file: string;
}
```

**Usage Examples:**

```typescript
// Delete a file
const result = await web.files.delete({
  file: 'F1234567890'
});

if (result.ok) {
  console.log('File deleted successfully');
}

// Delete multiple files
const filesToDelete = ['F1111111111', 'F2222222222', 'F3333333333'];

for (const fileId of filesToDelete) {
  try {
    await web.files.delete({ file: fileId });
    console.log(`Deleted file: ${fileId}`);
  } catch (error) {
    console.error(`Failed to delete file ${fileId}:`, error.message);
  }
}
```

### Public URL Management

Manage public sharing URLs for files.

```typescript { .api }
/**
 * Enable public sharing for a file and get the URL
 * @param options - Share parameters
 * @returns Promise resolving to public URL details
 */
files.sharedPublicURL(options: FilesSharedPublicURLArguments): Promise<FilesSharedPublicURLResponse>;

/**
 * Revoke public sharing for a file
 * @param options - Revoke parameters
 * @returns Promise resolving to revocation confirmation
 */
files.revokePublicURL(options: FilesRevokePublicURLArguments): Promise<FilesRevokePublicURLResponse>;

interface FilesSharedPublicURLArguments {
  /** File ID to enable public sharing for */
  file: string;
}

interface FilesRevokePublicURLArguments {
  /** File ID to revoke public sharing for */
  file: string;
}
```

**Usage Examples:**

```typescript
// Enable public sharing
const publicURL = await web.files.sharedPublicURL({
  file: 'F1234567890'
});

console.log('Public URL:', publicURL.file.permalink_public);

// Revoke public sharing
await web.files.revokePublicURL({
  file: 'F1234567890'
});

console.log('Public sharing revoked');
```

### Legacy File Upload

Legacy file upload method (use uploadV2 for new applications).

```typescript { .api }
/**
 * Upload a file (legacy method - use uploadV2 instead)
 * @param options - Upload parameters
 * @returns Promise resolving to upload result
 */
files.upload(options: FilesUploadArguments): Promise<FilesUploadResponse>;

interface FilesUploadArguments {
  /** File contents as string, Buffer, or Stream */
  file?: string | Buffer | NodeJS.ReadableStream;
  /** File contents (alternative to file parameter) */
  content?: string;
  /** Filename of file */
  filename?: string;
  /** Title of file */
  title?: string;
  /** Initial comment to add to file */
  initial_comment?: string;
  /** Comma-separated list of channel names or IDs */
  channels?: string;
  /** A file type identifier */
  filetype?: string;
  /** Syntax type of the snippet being uploaded */
  snippet_type?: string;
  /** Thread timestamp to upload to a thread */
  thread_ts?: string;
}
```

**Usage Examples:**

```typescript
// Legacy upload (prefer uploadV2)
const legacyUpload = await web.files.upload({
  channels: '#general',
  content: 'Hello, world!',
  filename: 'hello.txt',
  title: 'Greeting File'
});

console.log('Legacy upload result:', legacyUpload.file.id);
```

### File Comments

Manage comments on files.

```typescript { .api }
/**
 * Delete a comment on a file
 * @param options - Delete comment parameters
 * @returns Promise resolving to deletion result
 */
files.comments.delete(options: FilesCommentsDeleteArguments): Promise<FilesCommentsDeleteResponse>;

interface FilesCommentsDeleteArguments {
  /** File to delete comment from */
  file: string;
  /** ID of the comment to delete */
  id: string;
}
```

**Usage Examples:**

```typescript
// Delete a file comment
await web.files.comments.delete({
  file: 'F1234567890',
  id: 'Fc1234567890'
});

console.log('Comment deleted');
```

### Remote Files

Manage external files stored outside of Slack.

```typescript { .api }
/**
 * Add a remote file
 * @param options - Add remote file parameters
 * @returns Promise resolving to remote file details
 */
files.remote.add(options: FilesRemoteAddArguments): Promise<FilesRemoteAddResponse>;

/**
 * Get information about a remote file
 * @param options - Remote file info parameters
 * @returns Promise resolving to remote file details
 */
files.remote.info(options: FilesRemoteInfoArguments): Promise<FilesRemoteInfoResponse>;

/**
 * Remove a remote file
 * @param options - Remove parameters
 * @returns Promise resolving to removal confirmation
 */
files.remote.remove(options: FilesRemoteRemoveArguments): Promise<FilesRemoteRemoveResponse>;

interface FilesRemoteAddArguments {
  /** Creator defined GUID for the file */
  external_id: string;
  /** URL of the remote file */
  external_url: string;
  /** Title of the file */
  title: string;
  /** Type of file */
  filetype?: string;
  /** File size in bytes */
  indexable_file_contents?: string;  
  /** Preview of the document */
  preview_image?: string;
}
```

**Usage Examples:**

```typescript
// Add remote file
const remoteFile = await web.files.remote.add({
  external_id: 'gdrive-doc-123',
  external_url: 'https://docs.google.com/document/d/abc123',
  title: 'Project Specification',
  filetype: 'gdoc'
});

// Get remote file info
const remoteInfo = await web.files.remote.info({
  file: remoteFile.file.id
});

// Remove remote file
await web.files.remote.remove({
  file: remoteFile.file.id
});
```

## Types

```typescript { .api }
interface FilesCompleteUploadExternalResponse {
  id: string;
  created: number;
  timestamp: number;
  name: string;
  title: string;
  mimetype: string;
  filetype: string;
  pretty_type: string;
  user: string;
  size: number;
  mode: string;
  is_external: boolean;
  external_type: string;
  is_public: boolean;
  public_url_shared: boolean;
  display_as_bot: boolean;
  username: string;
  url_private: string;
  url_private_download: string;
  permalink: string;
  permalink_public?: string;
  thumb_64?: string;
  thumb_80?: string;
  thumb_360?: string;
  thumb_360_w?: number;
  thumb_360_h?: number;
  thumb_480?: string;
  thumb_480_w?: number;
  thumb_480_h?: number;
  thumb_160?: string;
  thumb_720?: string;
  thumb_720_w?: number;
  thumb_720_h?: number;
  thumb_800?: string;
  thumb_800_w?: number;
  thumb_800_h?: number;
  thumb_960?: string;
  thumb_960_w?: number;
  thumb_960_h?: number;
  thumb_1024?: string;
  thumb_1024_w?: number;
  thumb_1024_h?: number;
  original_w?: number;
  original_h?: number;
  thumb_tiny?: string;
}

interface FilesInfoResponse extends WebAPICallResult {
  file: {
    id: string;
    created: number;
    timestamp: number;
    name: string;
    title: string;
    mimetype: string;
    filetype: string;
    pretty_type: string;
    user: string;
    size: number;
    url_private: string;
    url_private_download: string;
    permalink: string;
    permalink_public?: string;
    channels: string[];
    groups: string[];
    ims: string[];
    comments_count?: number;
  };
  comments?: FileComment[];
  paging?: {
    count: number;
    total: number;
    page: number;
    pages: number;
  };
}

interface FileComment {
  id: string;
  created: number;
  timestamp: number;
  user: string;
  comment: string;
}

interface FilesListResponse extends WebAPICallResult {
  files: FilesInfoResponse['file'][];
  paging: {
    count: number;
    total: number;
    page: number;
    pages: number;
  };
}
```