---
source_url: https://www.pubnub.com/docs/sdks/objective-c/api-reference/files
title: File Sharing API for Objective-C SDK
updated_at: 2026-05-22T11:07:00.432Z
sdk_name: PubNub Objective-C SDK
sdk_version: 7.0.2
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# File Sharing API for Objective-C SDK

PubNub Objective-C SDK, use the latest version: 7.0.2

Install:

```bash
pod install PubNub@7.0.2
```

You can upload and share files up to 5 MB on PubNub. Common uses include sharing images in chat apps and documents in healthcare.

When a file is uploaded on a `channel`, it's stored and managed using a storage service, and associated with your key. Subscribers to that `channel` receive a file event which contains a file `ID`, `filename`, and optional `description`.

## Send file

Upload the file to a specified channel.

This method covers the entire process of sending a file, including preparation, uploading the file to a cloud storage service, and post-uploading messaging on a channel.

For the last messaging step, `sendFileWithRequest` internally calls the [publishFileMessageWithRequest](#publish-file-message) method to publish a message on the channel.

The published message contains metadata about the file, such as the file identifier and name, enabling others on the channel to find out about the file and access it.

For details on the method that publishes the file message, see [Publish file message](#publish-file-message).

### Method(s)

```objectivec
- (void)sendFileWithRequest:(PNSendFileRequest *)request 
                 completion:(nullable PNSendFileCompletionBlock)block;
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| request | PNSendFileRequest | Yes |  | `Send file` request with all information about file and where it should be uploaded. |
| block | PNSendFileCompletionBlock | Optional |  | `Send file` file request completion block. |

#### PNSendFileRequest

| Parameter | Description |
| --- | --- |
| `fileMessageMetadata`Type: NSDictionaryDefault: n/a | `NSDictionary` with values to be used by PubNub service to filter file messages. |
| `fileMessageTTL`Type: NSUIntegerDefault: 0 | How long the message should be stored in the channel's storage. Set to `0` (zero) to store the message according to the key's retention policy. |
| `fileMessageStore`Type: BOOLDefault: YES | Whether to store published file messages in the channel's history. |
| `message`Type: idDefault: n/a | Message to be sent along with the file to the specified `channel`. |
| `filename` *Type: NSStringDefault: n/a | Name to be used to store uploaded data. This is set by default only if the request is created with `requestWithChannel:fileURL:`. |

:::warning Deprecated parameter
The `cipherKey` parameter in this method is deprecated. We recommend that you configure the [crypto module](https://www.pubnub.com/docs/sdks/objective-c/api-reference/configuration#cryptomodule) on your PubNub instance instead. If you pass `cipherKey` as an argument, it overrides the crypto module configuration and the legacy encryption with 128-bit cipher key entropy is used.
:::

### Sample code

```objectivec
#import <Foundation/Foundation.h>
#import <PubNub/PubNub.h>

// Basic configuration
PNConfiguration *config = [PNConfiguration configurationWithPublishKey:@"demo"
                                                          subscribeKey:@"demo"
                                                                userID:@"fileUser"];

// Optional: Configure encryption for files
config.cryptoModule = [PNCryptoModule AESCBCCryptoModuleWithCipherKey:@"enigma"
                                           randomInitializationVector:YES];

// Create a PubNub client instance
PubNub *client = [PubNub clientWithConfiguration:config];

// Add listener for PubNub events
[client addListener:self];

// Sending file from byte data object
NSData *content = [@"This is a sample file uploaded using PubNub File API." dataUsingEncoding:NSUTF8StringEncoding];

// Create the file send request
PNSendFileRequest *request = [PNSendFileRequest requestWithChannel:@"file-channel"
                                                          fileName:@"sample.txt"
                                                              data:content];

// Add optional parameters
request.message = @{@"description": @"Sample text file upload"};
request.fileMessageMetadata = @{@"type": @"text", @"size": @"small"};
request.fileMessageStore = YES;

NSLog(@"Sending file binary data as: sample.txt");

// Send the file
[client sendFileWithRequest:request completion:^(PNSendFileStatus *status) {
    if (!status.isError) {
        NSLog(@"✅ File uploaded successfully!");
        NSLog(@"File ID: %@", status.data.fileIdentifier);
        NSLog(@"Stored as: %@", status.data.fileName);
        NSLog(@"Timetoken: %@", status.data.timetoken);
    } else {
        NSLog(@"❌ Error uploading file: %@", status.errorData.information);
        
        if (status.data.fileUploaded) {
            NSLog(@"⚠️ File was uploaded but message publishing failed.");
            // Here you could implement retry logic for just the message publishing
        } else {
            NSLog(@"⚠️ File upload failed completely.");
            // Here you could implement retry logic for the whole file upload
        }
    }
}];

// Subscribe to a file channel
PNSubscribeRequest *request = [PNSubscribeRequest requestWithChannels:@[@"file-channel"]
                                                        channelGroups:nil];
    
[self.client subscribeWithRequest:request];

// Required PNEventsListener methods
- (void)client:(PubNub *)client didReceiveStatus:(PNStatus *)status {
    // Checking connectivity only using subscribe operation.
    if (status.operation != PNSubscribeOperation) return;
    
    if (status.category == PNConnectedCategory) {
        NSLog(@"✅ Successfully connected to PubNub!");
    } else if (status.isError) {
        NSLog(@"❌ PubNub connection error: %@", status);
    }
}

- (void)client:(PubNub *)client didReceiveMessage:(PNMessageResult *)message {
    NSLog(@"Received message: %@ on channel: %@", message.data.message, message.data.channel);
}
```

### Response

```objectivec
@interface PNSendFileData : PNServiceData

// Unique identifier assigned to the file during upload
@property (nonatomic, nullable, readonly, strong) NSString *fileIdentifier;

// Time at which the file information message was published.
@property (nonatomic, nullable, readonly, strong) NSNumber *timetoken;

// Name under which the uploaded file is stored
@property (nonatomic, nullable, readonly, strong) NSString *fileName;

/**
 * Whether the file uploaded or not.
 *
 * This property should be used during error handling to identify whether the
 * send-file request should be resent, or if you just need to call
 * file message publish.
*/
@property (nonatomic, readonly, assign) BOOL fileUploaded;

@end

@interface PNSendFileStatus : PNAcknowledgmentStatus

// Send file request processed information.
@property (nonatomic, readonly, strong) PNSendFileData *data;

@end
```

### Other examples

#### Send file with push notification

:::tip Trigger push notifications when sharing files
To send mobile push notifications when sharing a file, include `pn_apns` (for iOS) and/or `pn_fcm` (for Android) payloads in the `message` parameter of the `sendFileWithRequest` method.
When PubNub detects these reserved keys, it automatically forwards the push notification to the appropriate push service (APNs or FCM) for all devices registered on the channel.
:::

```objectivec
NSDictionary *message = @{
  @"text": @"Check out this file!",
  @"pn_apns": @{
      @"aps": @{
          @"alert": @{@"title": @"New File", @"body": @"A file was shared"}
      },
      @"pn_push": @[@{
          @"targets": @[@{@"topic": @"com.yourapp.bundleid", @"environment": @"production"}],
          @"version": @"v2"
      }]
  },
  @"pn_fcm": @{
      @"notification": @{@"title": @"New File", @"body": @"A file was shared"}
  }
};

PNSendFileRequest *request = [PNSendFileRequest requestWithChannel:@"my-channel"
                                                         fileURL:fileURL];
request.filename = @"example.txt";
request.message = message;

[self.client sendFileWithRequest:request completion:^(PNSendFileStatus *status) {
  // Handle result
}];
```

For more details on push notification payload structure, see the [iOS Push](https://www.pubnub.com/docs/general/push/ios) and [Android Push](https://www.pubnub.com/docs/general/push/android) documentation. To prevent the sender from receiving their own push notification, add their device token to `excluded_devices` in the `pn_push` targets.

#### Upload binary data

```objectivec
NSData *data = [[NSUUID UUID].UUIDString dataUsingEncoding:NSUTF8StringEncoding];
PNSendFileRequest *request = [PNSendFileRequest requestWithChannel:@"channel"
                                                          fileName:@"cat_picture.jpg"
                                                              data:data];

[self.client sendFileWithRequest:request completion:^(PNSendFileStatus *status) {
    if (!status.isError) {
        /**
         * File upload successfully completed.
         * Uploaded file information available here:
         *   status.data.fileIdentifier - unique file identifier
         *   status.data.fileName - name which has been used to store file
         */
    } else {
        /**
         * Handle send file error. Check 'category' property to find out possible issue
         * because of which request did fail.
         *
         * Check 'status.data.fileUploaded' to figure out whether request should be resent or
         * only file message publish should be called.
         */
    }
}];
```

#### Upload using stream

```objectivec
NSInputStream *stream = ...;
NSUInteger streamSize = /* size of data in stream */;
PNSendFileRequest *request = [PNSendFileRequest requestWithChannel:@"channel"
                                                          fileName:@"image.png"
                                                            stream:stream
                                                              size:streamSize];

[self.client sendFileWithRequest:request completion:^(PNSendFileStatus *status) {
    if (!status.isError) {
        /**
         * File upload successfully completed.
         * Uploaded file information available here:
         *   status.data.fileIdentifier - unique file identifier
         *   status.data.fileName - name which has been used to store file
         */
    } else {
        /**
         * Handle send file error. Check 'category' property to find out possible issue
         * because of which request did fail.
         *
         * Check 'status.data.fileUploaded' to figure out whether request should be resent or
         * only file message publish should be called.
         */
    }
}];
```

### Returns

Same as from basic usage.

## List channel files

Retrieve list of files uploaded to `Channel`.

### Method(s)

```objectivec
- (void)listFilesWithRequest:(PNListFilesRequest *)request 
                  completion:(PNListFilesCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNListFilesRequest](#pnlistfilesrequest) | `List files` request with all information which should be used to fetch channel's files list. |
| `block` *Type: PNListFilesCompletionBlock | `List files` request completion block. |

#### PNListFilesRequest

| Parameter | Description |
| --- | --- |
| `next`Type: NSStringDefault: n/a | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `limit`Type: NSUIntegerDefault: 100 | Number of files to return in response. |

### Sample code

```objectivec
PNListFilesRequest *request = [PNListFilesRequest requestWithChannel:@"channel"];
request.limit = 20;
request.next = ...;

[self.client listFilesWithRequest:request
                       completion:^(PNListFilesResult *result, PNErrorStatus *status) {
    if (!status.isError) {
        /**
         * Uploaded files list successfully fetched.
         *   result.data.files - List of uploaded files (information).
         *   result.data.next - Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
         *   result.data.count - Total number of files uploaded to channel.
         */
    } else {
        /**
         * Handle fetch files list error. Check 'category' property to find out possible issue
         * because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

### Response

```objectivec
@interface PNListFilesData : PNServiceData

// List of channel files.
@property (nonatomic, nullable, readonly, strong) NSArray<PNFile *> *files;

// Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off.
@property (nonatomic, nullable, readonly, strong) NSString *next;

// How many files has been returned.
@property (nonatomic, readonly, assign) NSUInteger count;

@end

@interface PNListFilesResult : PNResult

// List files request processed information.
@property (nonatomic, readonly, strong) PNListFilesData *data;

@end
```

## Get file URL

Generate a URL to download a file from the target `channel`.

### Method(s)

```objectivec
- (nullable NSURL *)downloadURLForFileWithName:(NSString *)name 
                                    identifier:(NSString *)identifier 
                                     inChannel:(NSString *)channel;
```

| Parameter | Description |
| --- | --- |
| `name` *Type: NSString | Name under which uploaded `file` is stored for `channel`. |
| `identifier` *Type: NSString | Unique `file` identifier which has been assigned during `file` upload. |
| `channel` *Type: NSString | Name of channel within which `file` with `name` has been uploaded. |

### Sample code

```objectivec
NSURL *url = [self.client downloadURLForFileWithName:@"user_profile.png"
                                          identifier:@"<file-identifier>"
                                           inChannel:@"lobby"];
```

### Returns

URL which can be used to download remote file with specified `name` and `identifier`.

## Download file

Download a file from the specified `channel`.

### Method(s)

```objectivec
- (void)downloadFileWithRequest:(PNDownloadFileRequest *)request 
                     completion:(PNDownloadFileCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNDownloadFileRequest](#pndownloadfilerequest) | `Download file` request with information about file which should be downloaded. |
| `block` *Type: PNDownloadFileCompletionBlock | `Download file` request completion block. |

#### PNDownloadFileRequest

| Parameter | Description |
| --- | --- |
| `targetURL`Type: NSURLDefault: Temporary location | URL where the downloaded file should be stored locally. A file downloaded to a temporary location is removed after the completion block returns. |

:::warning Deprecated parameter
The `cipherKey` parameter in this method is deprecated. We recommend that you configure the [crypto module](https://www.pubnub.com/docs/sdks/objective-c/api-reference/configuration#cryptomodule) on your PubNub instance instead. If you pass `cipherKey` as an argument, it overrides the crypto module configuration and the legacy encryption with 128-bit cipher key entropy is used.
:::

### Sample code

```objectivec
PNDownloadFileRequest *request = [PNDownloadFileRequest requestWithChannel:@"lobby"
                                                                identifier:@"<file-identifier>"
                                                                      name:@"user_profile.png"];
request.targetURL = ...;

[self.client downloadFileWithRequest:request
                          completion:^(PNDownloadFileResult *result, PNErrorStatus *status) {

    if (!status.isError) {
        /**
         * File successfully has been downloaded.
         *   status.data.location - location where downloaded file can be found
         *   status.data.temporary - whether file has been downloaded to temporary storage and
         *                           will be removed on completion block return.
         */
    } else {
        /**
         * Handle file download error. Check 'category' property to find out possible issue
         * because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

### Response

```objectivec
@interface PNDownloadFileData : PNServiceData

/**
 * Whether file is temporary or not.
 *
 * Temporary file will be removed as soon as completion block will exit. Make sure
 * to move temporary files (w/o scheduling task on secondary thread) to persistent
 * location.
 */
@property (nonatomic, readonly, assign, getter = isTemporary) BOOL temporary;

// Location where downloaded file can be found.
@property (nonatomic, readonly, nullable, readonly, strong) NSURL *location;

@end

@interface PNDownloadFileResult : PNResult

// Download file request processed information.
@property (nonatomic, readonly, strong) PNDownloadFileData *data;

@end
```

## Delete file

Delete a file from the specified `channel`.

### Method(s)

```objectivec
- (void)deleteFileWithRequest:(PNDeleteFileRequest *)request 
                   completion:(nullable PNDeleteFileCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: PNDeleteFileRequest | `Delete file` request with all information about file for removal. |
| `block`Type: PNDeleteFileCompletionBlock | `Delete file` request completion block. |

### Sample code

```objectivec
PNDeleteFileRequest *request = [PNDeleteFileRequest requestWithChannel:@"channel"
                                                            identifier:@"<file-identifier>"
                                                                  name:@"greetings.txt"];

[self.client deleteFileWithRequest:request completion:^(PNAcknowledgmentStatus *status) {
    if (!status.isError) {
        // File successfully has been deleted.
    } else {
        /**
         * Handle file delete error. Check 'category' property to find out possible issue
         * because of which request did fail.
         *
         * Request can be resent using: [status retry]
         */
    }
}];
```

### Response

```objectivec
@interface PNErrorData : PNServiceData

// Stringified error information.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNAcknowledgmentStatus : PNErrorStatus

// Whether status object represent error or not.
@property (nonatomic, readonly, assign, getter = isError) BOOL error;

// Additional information related to error status object.
@property (nonatomic, readonly, strong) PNErrorData *errorData;

@end
```

## Publish file message

Publish the uploaded file message to a specified channel.

This method is called internally by [sendFileWithRequest](#send-file) as part of the file-sending process to publish the message with the file (already uploaded in a storage service) on a channel.

This message includes the file's unique identifier and name elements, which are needed to construct download links and inform channel subscribers that the file is available for download.

You can call this method when `sendFileWithRequest` fails and returns the `status.operation === PNPublishFileMessageOperation` error. In that case, you can use the data from the `status` object to try again and use `publishFileMessageWithRequest` to manually resend a file message to a channel without repeating the upload step.

### Method(s)

```objectivec
- (void)publishFileMessageWithRequest:(PNPublishFileMessageRequest *)request 
                           completion:(nullable PNPublishCompletionBlock)block;
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNPublishFileMessageRequest](#pnpublishfilemessagerequest) | `File message publish` request with all information about uploaded file. |
| `block`Type: PNPublishCompletionBlock | `File message publish` request completion block. |

#### PNPublishFileMessageRequest

| Property | Description |
| --- | --- |
| `identifier`Type: NSString* | Unique identifier provided during file upload. |
| `filename`Type: NSString* | Name with which uploaded data has been stored. |
| `customMessageType`Type: NSString* | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

You can also set any parameters from the `PNBasePublishRequest` request:

| Property | Description |
| --- | --- |
| `arbitraryQueryParameters`Type: NSDictionary* | Arbitrary percent-encoded query parameters which should be sent along with the original API call. |
| `preparedMetadata`Type: NSString* | Serialized `NSDictionary` with values used by PubNub service to filter messages. |
| `replicate`Type: BOOL | Whether the message should be replicated across the PubNub Real-Time Network and sent simultaneously to all subscribed clients on a channel. |
| `store`Type: BOOL | Whether `published` data should be stored and available with the history API or not. |
| `metadata`Type: NSDictionary* | `NSDictionary` with values used by PubNub service to filter messages. |
| `channel`Type: NSString* | Name of channel to which the message should be published. |
| `message`Type: id | Message to be published. The object is serialized into JSON (supports `NSString`, `NSNumber`, `NSArray`, `NSDictionary`). If you configured a [crypto module](https://www.pubnub.com/docs/sdks/objective-c/api-reference/configuration#cryptomodule), the message is encrypted. |
| `ttl`Type: NSUInteger | Duration for which the message should be stored in the channel's storage. Passing \b 0 will store the message according to retention policy. |
| `retried`Type: BOOL | Indicates whether the request is repeatedly sent to retry after a recent failure. |

### Sample code

```objectivec
PNPublishFileMessageRequest *request = [PNPublishFileMessageRequest requestWithChannel:@"channel"
                                                                        fileIdentifier:@"fileIdentifier"
                                                                                  name:@"fileName"];
request.customMessageType = @"file-message";

[self.client publishFileMessageWithRequest:request completion:^(PNPublishStatus *status) {
    if (!status.isError) {
        // File message successfully published.
    } else {
        // Handle file message publish error. Check 'category' property to find out possible
        // issue because of which request did fail.
        //
        // Request can be resent using: [status retry];
    }
}];
```

### Response

```objectivec
@interface PNPublishData : PNServiceData

/**
 * Service-provided time stamp at which message has been pushed to remote
 * data object live feed.
 */
@property (nonatomic, readonly, strong) NSNumber *timetoken;

// Service-provide information about service response message.
@property (nonatomic, readonly, strong) NSString *information;

@end

@interface PNPublishStatus : PNAcknowledgmentStatus

// Stores reference on publish request processing status information.
@property (nonatomic, readonly, strong) PNPublishData *data;

@end
```