PubNub Logo Docs
Support Contact Sales Login Try Our APIs

›File sharing

Collapse all
Dark mode

Home

  • Home

First steps

  • Set up your account
  • Get the SDK
  • Initialize PubNub
  • Identify users and devices
  • Send messages
  • Receive messages
  • Retrieve old messages
  • Check user presence
  • Add custom metadata
  • Manage access
  • Add serverless business logic
  • Send push notifications

Setup

  • PubNub account
  • Application
  • Users & devices
  • Connection management
  • Data security
  • Data persistence
  • API limits

Chat

  • In-App Chat

SDKs

  • SDKs

Messages

  • Publish
  • Receive
  • Actions
  • Payload type conventions

Channels

  • Basics
  • Subscription
  • Naming conventions

User presence

  • Basics
  • Events
  • State
  • Webhooks

Metadata

  • Channel
  • User
  • Membership

Message Persistence

  • Message Persistence

File sharing

  • File sharing

Access management

  • Manage access

Push notifications

  • Basics
  • iOS
  • Android
  • Troubleshooting

Best practices

  • Architectural choices
  • Message aggregation
  • Friend list & status feed
  • Troubleshooting
  • Migration guides

Serverless processing

    EVENTS & ACTIONS

    • Basics
    • Configure Events & Actions

    FUNCTIONS

    • Basics
    • Development guidelines
    • Functions API
    • Custom integrations

Debug Console
Network Status

File Sharing

In addition to messages and signals, PubNub also allows users to upload and share files.

The most common scenarios where you may need to share files are in social apps to share images or in medical apps to share medical records. You can upload and share videos, images, or documents of up to 5 MB in size each.

Sending Files

Sending a file is a lot like publishing a message; you must specify the channel on which to send the file and provide the actual file. You can also optionally include some text to use as a caption for the file.

You can also encrypt files using AES-256 Encryption. To send such files, you must either have a cipher key defined in your initial client configuration or specify the cipher key parameter directly in each request. Other clients will have to provide this key when downloading the file to decrypt the content successfully.

The code below sends the file cat_picture.jpg on the channel my_channel:

JavaScript
C#
Go
Objective-C
Android
Python
Swift

Go to SDK

// web
const input = document.querySelector('input[file]');

input.addEventListener('change', async () => {
const file = input.files[0];

const result = await pubnub.sendFile({
channel: 'my_channel',
file: file,
});
});

// Node.js
import fs from 'fs';

const myFile = fs.createReadStream('./cat_picture.jpg');

const result = await pubnub.sendFile({
channel: 'my_channel',
file: { stream: myFile, name: 'cat_picture.jpg', mimeType: 'image/jpeg' },
});

// React
const result = await pubnub.sendFile({
channel: 'my_channel',
message: {
test: 'message',
value: 42
},
file: {
uri: imageUri,
name: 'cat_picture.jpg',
mimeType: 'image/jpeg',
},
});

Go to SDK

PNResult<PNFileUploadResult> fileUploadResponse = await pubnub.SendFile()
.Channel("my_channel")
.File("cat_picture.jpg") // checks the bin folder if no path is provided
.Message("Look at this photo!")
.ExecuteAsync();
PNFileUploadResult fileUploadResult = fileUploadResponse.Result;
PNStatus fileUploadStatus = fileUploadResponse.Status; // contains troubleshooting info
if (!fileUploadStatus.Error && fileUploadResult != null) // checks if successful
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileUploadResult));
}
else
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileUploadStatus));
}

Go to SDK

file, err := os.Open("cat_picture.jpg")
defer file.Close()
if err != nil {
panic(err)
}
resSendFile, statusSendFile, errSendFile := pn.SendFile().
Channel("my_channel").
Message("Look at this photo!").
Name("cat_picture.jpg").
File(file).Execute()
fmt.Println(resSendFile, statusSendFile, errSendFile)
fmt.Println(resSendFile.Data.ID)

Go to SDK

NSURL *localFileURL = ...;
PNSendFileRequest *request = [PNSendFileRequest requestWithChannel:@"my_channel"
fileURL:localFileURL];

[self.client sendFileWithRequest:request completion:^(PNSendFileStatus *status) {
if (!status.isError) {
/**
* File upload successfully completed.
* Uploaded file information is available here:
* status.data.fileIdentifier is the unique file identifier
* status.data.fileName is the name used to store the file
*/

} else {
/**
* Handle send file error. Check the 'category' property for reasons
* why the request may have failed.
*
* Check 'status.data.fileUploaded' to determine whether to resend the
* request or if only file message publish should be called.
*/

}
}];

Go to SDK

pubnub.sendFile()
.channel("my_channel")
.fileName("cat_picture.jpg")
.inputStream(inputStream)
.message("Look at this photo!")
.async(new PNCallback<PNFileUploadResult>() {
@Override
public void onResponse(PNFileUploadResult result, PNStatus status) {
if (!status.isError()) {
System.out.println("send timetoken: " + result.getTimetoken());
System.out.println("send status: " + result.getStatus());
System.out.println("send fileId: " + result.getFile().getId());
System.out.println("send fileName: " + result.getFile().getName());
}
System.out.println("send status code: " + status.getStatusCode());
}
});

Go to SDK

# synchronous
with open("cat_picture.jpg", "rb") as fd:
envelope = pubnub.send_file().
channel("my_channel").
file_name("cat_picture.jpg").
message({"test_message": "test"}).
should_store(True).
ttl(222).
file_object(fd).
cipher_key("secret").sync()

# multithreaded asynchronous
def callback(response, status):
pass

fd = open("cat_picture.jpg", "rb") as fd:
pubnub.send_file().
channel("my_channel").
file_name("cat_picture.jpg").
message({"test_message": "test"}).
should_store(True).
ttl(222).
file_object(fd.read()).
cipher_key("secret").pn_async(callback)

Go to SDK

pubnub.send(
.file(url: "cat_picture.jpg"),
channel: "my_channel",
remoteFilename: "cat_picture.jpg",
publishRequest: .init(additionalMessage: ["text": "Look at this photo!"])
) { (fileTask) in
print("The task \(fileTask.urlSessionTask.taskIdentifier) has started uploading; no need to call `resume()`")
print("If needed, the `URLSessionUploadTask` can be accessed with `fileTask.urlSessionTask`")
print("You can use `fileTask.progress` to populate a `UIProgressView`/`ProgressView` ")
} completion: { (result) in
switch result {
case let .success((task, file, publishedAt)):
print("The file with an ID of \(file.fileId) was uploaded at \(publishedAt) timetoken) ")
case let .failure(error):
print("An error occurred while uploading the file: \(error.localizedDescription)")
}
}

Even though you upload and share the files directly from the client, it's the storage service that stores and manages the actual files for each key.

Once the file has been uploaded to the storage service, subscribers of a particular channel receive a file message. With this file message (which contains a description, filename, and file ID) you can use our SDKs to generate a URL to display the file or download the file directly. Refer to Retrieving Files for more information.

Enable the Feature

Files is an optional feature that you must enable by turning on the Files toggle for your keys in the Admin Portal.

File Operations

Apart from sending files, you can list all files that were sent to a channel or delete a file that has been previously uploaded to the storage service. Much like with regular messages, you can also search through historical file messages using the History API if you enabled Message Persistence on your API key. The information returned by the History API allows you to either display the file in the browser or download it.

Refer to the Files section in the SDK documentation to learn more about operations on files.

Receiving Files

In order to receive a file, the receiving client should be listening to an event of type file, and should subscribe to a channel in which the file is being sent. There is no need to subscribe any differently to a channel for receiving a file.

Retrieving Files

Retrieving files is a two-step process accomplished using the History API and Files-related SDK methods. To retrieve a file:

  1. Get the file message using History API or the listFiles method
  2. Display or download the file using dedicated SDK methods based on the obtained file information
File URLs

Neither the History API nor the listFiles method returns file URLs. They return file-specific information like the file's name and ID that you need to display or download the file.

When you fetch file messages using History API, the response includes the file details (ID, filename) and a message type of 4 that indicates it's a file message. You can use this information to display or download the file.

Display and Download Files

Apart from the optional description, a file message contains the ID and name of the file.

As a file message does not contain the file URL, you must use one of the available SDK methods to construct the file URL to either display the file or download it.

The following code returns the URL of the cat_picture.jpg file sent to channel my_channel:

JavaScript
C#
Go
Objective-C
Android
Python
Swift

Go to SDK

const result = pubnub.getFileUrl({ channel: 'my_channel', id: 'd9515cb7-48a7-41a4-9284-f4bf331bc770', name: 'cat_picture.jpg' });

Go to SDK

PNResult<PNFileUrlResult> getFileUrlResponse = await pubnub.GetFileUrl()
.Channel("my_channel")
.FileId("d9515cb7-48a7-41a4-9284-f4bf331bc770")
.FileName("cat_picture.jpg")
.ExecuteAsync();
PNFileUrlResult getFileUrlResult = getFileUrlResponse.Result;
PNStatus getFileUrlStatus = getFileUrlResponse.Status;
if (getFileUrlResult != null)
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(getFileUrlResult));
}
else
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(getFileUrlStatus));
}

Go to SDK

resGetFile, statusGetFile, errGetFile := pn.GetFileURL().
Channel("my_channel").
ID("d9515cb7-48a7-41a4-9284-f4bf331bc770").
Name("cat_picture.jpg").Execute()
fmt.Println(resGetFile, statusGetFile, errGetFile)
fmt.Println(resGetFile.URL)

Go to SDK

NSURL *url = [self.client downloadURLForFileWithName:@"cat_picture.jpg"
identifier:@"<file-identifier>"
inChannel:@"my_channel"];

Go to SDK

pubnub.getFileUrl()
.channel("my_channel")
.fileName("cat_picture.jpg")
.fileId("d9515cb7-48a7-41a4-9284-f4bf331bc770")
.async(new PNCallback<PNFileUrlResult>() {
@Override
public void onResponse(PNFileUrlResult result, PNStatus status) {
if (!status.isError()) {
System.out.println("getUrl fileUrl: " + result.getUrl());
}
System.out.println("getUrl status code: " + status.getStatusCode());
}
});

Go to SDK

# Synchronous:
envelope = pubnub.get_file_url().
channel("my_channel").
file_id("fileID").
file_name("cat_picture.jpg").sync()


# Multithreaded asynchronous:
def callback(response, status):
pass

pubnub.get_file_url().
channel("my_channel").
file_id("fileID").
file_name("cat_picture.jpg").sync()

Go to SDK

do {
let downloadURL = try pubnub.generateFileDownloadURL(channel: "my_channel", fileId: "fileID", filename: "cat_picture.jpg")
} catch {
print("An error occurred generating the URL: \(error.localizedDescription)")
}

The response to this call is the file URL which you can use to display the file in the browser.

You need the same set of file information to download the file. The following code downloads the file cat_picture.jpg sent to the channel my_channel:

JavaScript
C#
Go
Objective-C
Android
Python
Swift

Go to SDK

// web
const file = await pubnub.downloadFile({
channel: 'my_channel',
id: '...',
name: 'cat_picture.jpg',
});

const myImageTag = document.createElement('img');
myImageTag.src = URL.createObjectURL(await file.toFile());

document.body.appendChild(myImageTag);

// Node.js using streams
import fs from 'fs'

const file = await pubnub.downloadFile({
channel: 'my_channel',
id: 'd9515cb7-48a7-41a4-9284-f4bf331bc770',
name: 'cat_picture.jpg',
});

const output = fs.createWriteStream('./cat_picture.jpg');
const fileStream = await file.toStream();

fileStream.pipe(output);

output.once('end', () => {
console.log('File saved to ./cat_picture.jpg');
});

// React
const file = await pubnub.downloadFile({
channel: 'my_channel',
id: imageId,
name: 'cat_picture.jpg'
});

let fileContent = await file.toBlob();

Go to SDK

PNResult<PNDownloadFileResult> fileDownloadResponse = await pubnub.DownloadFile()
.Channel("my_channel")
.FileId("d9515cb7-48a7-41a4-9284-f4bf331bc770")
.FileName("cat_picture.jpg")
.ExecuteAsync();
PNDownloadFileResult fileDownloadResult = fileDownloadResponse.Result;
PNStatus fileDownloadStatus = fileDownloadResponse.Status;
if (fileDownloadResult != null)
{
fileDownloadResult.SaveFileToLocal(downloadUrlFileName); // saves to bin folder if no path is provided
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileDownloadResult.FileName));
}
else
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(fileDownloadStatus));
}

Go to SDK

resDLFile, statusDLFile, errDLFile := pn.DownloadFile().
Channel("my_channel").
ID("d9515cb7-48a7-41a4-9284-f4bf331bc770").
Name("cat_picture.jpg").Execute()
if resDLFile != nil {
filepathOutput := "cat_picture.jpg"
out, _ := os.Create(filepathOutput)
_, err := io.Copy(out, resDLFile.File)

if err != nil {
fmt.Println(err)
}
}

Go to SDK

PNDownloadFileRequest *request = [PNDownloadFileRequest requestWithChannel:@"my_channel"
identifier:@"<file-identifier>"
name:@"cat_picture.jpg"];
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]
*/

}
}];

Go to SDK

pubnub.getFile()
.channel("my_channel")
.fileName("cat_picture.jpg")
.fileId("d9515cb7-48a7-41a4-9284-f4bf331bc770")
.async(new PNCallback<PNDownloadFileResult>() {
@Override
public void onResponse(PNDownloadFileResult result, PNStatus status) {
if (!status.isError()) {
System.out.println("getFile fileName: " + result.getFileName());
System.out.println("getFile byteStream: " + result.getByteStream());
}
System.out.println("getFile status code: " + status.getStatusCode());
}
});

Go to SDK

# synchronous:
download_envelope = pubnub.download_file().
channel("my_channel").
file_id("fileId").
file_name("cat_picture.jpg").sync()

# Multithreaded asynchronous:
def callback(response, status):
pass

pubnub.download_file().
channel("my_channel").
file_id("fileID").
file_name("cat_picture.jpg").pn_async(callback)

Go to SDK

let requestFile = PubNubLocalFileBase(
fileURL: URL(fileURLWithPath: "cat_picture.jpg"),
channel: "my_channel",
fileId: "fileId",
remoteFilename: "cat_picture.jpg"
)

pubnub.download(
file: requestFile, toFileURL: requestFile.fileURL
) { (fileTask: HTTPFileDownloadTask) in

print("The task \(fileTask.taskIdentifier) has started downloading; no need to call `resume()`")
print("If needed, the `URLSessionUploadTask` can be accessed with `fileTask.urlSessionTask`")
print("You can use `fileTask.progress` to populate a `UIProgressView`/`ProgressView` ")

} completion: { result in
switch result {
case let .success(task, newFile):
print("The file task \(task.taskIdentifier) downloaded successfully to \(newFile.fileURL), which might be different than \(requestFile.fileURL)")
print("This also might mean that \(newFile.filename) could be different from \(newFile.remoteFilename)")

case let .failure(error):
print("An error occurred while downloading the file: \(error.localizedDescription)")
}
}

List Files

If you're only interested in the actual files and not the file messages (which include the optional description of the uploaded file) that were sent, you can list up to 100 files sent to a particular channel. However, if there are more than 100 files to be returned, the more flag will be present in the response.

The code below returns the name, ID, size, and created timestamp for up to 100 files sent to the channel my_channel:

JavaScript
C#
Go
Objective-C
Android
Python
Swift

Go to SDK

const result = await pubnub.listFiles({ channel: 'my_channel' });

Go to SDK

PNResult<PNListFilesResult> listFilesResponse = await pubnub.ListFiles()
.Channel("my_channel")
.ExecuteAsync();
PNListFilesResult listFilesResult = listFilesResponse.Result;
PNStatus listFilesStatus = listFilesResponse.Status;
if (listFilesResult != null)
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(listFilesResult));
}
else
{
Console.WriteLine(pubnub.JsonPluggableLibrary.SerializeToJsonString(listFilesStatus));
}

Go to SDK

resListFile, statusListFile, errListFile := pn.ListFiles().
Channel("my_channel").Execute()
fmt.Println(resListFile, statusListFile, errListFile)
if resListFile != nil {
for _, m := range resListFile.Data {
fmt.Println(m.ID, m.Created, m.Name, m.Size)
}
}

Go to SDK

PNListFilesRequest *request = [PNListFilesRequest requestWithChannel:@"my_channel"];
request.limit = 100;
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 - cursor value to navigate to next fetched result page.
* 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 failed.
*
* Request can be resent using: [status retry]
*/

}
}];

Go to SDK

pubnub.listFiles()
.channel("my_channel")
.async(new PNCallback<PNListFilesResult>() {
@Override
public void onResponse(PNListFilesResult result, PNStatus status) {
if (!status.isError()) {
System.out.println("files status: " + result.getStatus());
System.out.println("files status: " + result.getNext());
System.out.println("files status: " + result.getCount());
System.out.println("files status: " + result.getCount());
for (PNUploadedFile file : result.getData()) {
System.out.println("files fileId: " + file.getId());
System.out.println("files fileName: " + file.getName());
System.out.println("files fileSize: " + file.getSize());
System.out.println("files fileCreated: " + file.getCreated());
}
}
System.out.println("files status code: " + status.getStatusCode());
}
});

Go to SDK

# synchronous
pubnub.list_files().channel("my_channel").sync()

# multithreaded asynchronous
def callback(response, status):
pass

pubnub.list_files().channel("my_channel").pn_async(callback)

Go to SDK

pubnub.listFiles(
channel: "my_channel"
) { result in
case let .success(response):
print("There are \(response.files.count) file(s) found")

if let nextPage = response.next {
print("The next page used for pagination: \(nextPage)")
}
case let .failure(error):
print("An error occurred while fetching the file list: \(error.localizedDescription)")
}
← Message PersistenceManage access →
  • Sending Files
  • File Operations
  • Receiving Files
  • Retrieving Files
    • Display and Download Files
    • List Files
© PubNub Inc. - Privacy Policy