Tier 2File09 / 29
File Upload: a two-step handshake, then a raw upload
Persistent State: files are effectively a fifth tier: durable like leaderboards/profile, but for binary data instead of JSON.
Uploading a file to a player's brainCloud account is a two-step handshake, not one call. prepareUserUpload tells brainCloud what's coming (path, name, size, sharing/overwrite flags) and returns an uploadId. uploadFile then performs the actual transfer against that id. The FileUploader JS example (repositories/js-examples/FileUploader) exercises this end to end, including the memory-only variant for uploading generated content, like a screenshot, without ever touching the local filesystem.
How it works
- Prepare first, upload second. prepareUserUpload(cloudPath, cloudFileName, isShareable, replaceIfExists, fileSize, callback) returns data.fileDetails.uploadId. Nothing is transferred yet; brainCloud just reserves the slot.
- The actual transfer is a separate call using that id. uploadFile(xhr, file, uploadId) takes a raw XMLHttpRequest already wired with progress/complete/error/abort listeners, plus the browser File object and the uploadId from step 1.
- Generated content skips the file picker entirely. uploadFileFromMemory(cloudPath, cloudFileName, isShareable, replaceIfExists, blob, callback) uploads a Blob directly. There's no prepareUserUpload handshake for this path, and no local file ever exists.
- Progress is tracked through the supplied XMLHttpRequest, not a brainCloud callback. xhr.upload.addEventListener("progress", ...) is standard browser API, wired before the upload call.
Code
Grab the file, guard the unselected case, then wire the XHRbraincloud-fileuploadtest.html:361-375
function uploadFile() {
var xhr = new XMLHttpRequest();
var file = document.getElementById('fileToUpload').files[0];
if(file === undefined) {
console.log("Please select a file in Step 2. to upload.");
document.getElementById("incomingResponse").innerHTML = "Error uploading file. Please select a file in Step 2. to upload. ";
}
var fileSize = file.size;
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);Step 1: reserve the upload, get an idbraincloud-fileuploadtest.html:378-391
brainCloud.file.prepareUserUpload(
document.getElementById("cloudPath").value,
document.getElementById("cloudFileName").value,
document.getElementById("isShareable").checked,
document.getElementById("replaceIfExists").checked,
fileSize,
function(result) {
if (result.status == 200) {
var uploadId = result.data.fileDetails.uploadId;
brainCloud.file.uploadFile(xhr, file, uploadId); // step 2, actual transfer
}
}
);Memory-only upload: no file picker, no prepare stepbraincloud-fileuploadtest.html:394-406
brainCloud.file.uploadFileFromMemory(
document.getElementById("cloudPath").value,
document.getElementById("cloudFileName").value,
document.getElementById("isShareable").checked,
document.getElementById("replaceIfExists").checked,
new Blob([document.getElementById("fileInMemoryContent").value], {type: 'text/plain'}),
function(result) { /* ... */ }
);Gotchas worth knowing up front
- prepareUserUpload and uploadFile are two different calls with two different jobs. The first reserves the slot and returns an id. The second does the byte transfer. Calling uploadFile without a fresh uploadId from prepareUserUpload leaves nothing to upload against.
- This method name was a real, live bug in the reference app until it was fixed. The example was calling prepareFileUpload, a method that doesn't exist on the File service, instead of prepareUserUpload. It's fixed now (js-examples@a0f3e56), which is also what makes this article's citations trustworthy: the code shown above is the corrected, confirmed-working version, not the version that was silently broken.
- Progress tracking is the XMLHttpRequest's job, not the SDK's. brainCloud hands back the transport primitive. Wiring progress/load/error/abort listeners is standard browser code, not a brainCloud callback pattern.
- uploadFileFromMemory is the right tool for generated content (screenshots, exported save data). It skips the two-step handshake entirely and uploads a Blob directly. No local file required.