// If you're using expo, this code will apply most to you. async function retrieveDirectUpload(uri: string) { const info = await FileSystem.getInfoAsync(uri, { size: true, md5: true, }); // the expo docs for getInfoAsync don't specify that the md5 is in hex, which took a while to figure out const base64 = Buffer.from(info.md5, 'hex').toString('base64'); const splitUri = info.uri.split('/'); const filename = splitUri[splitUri.length - 1]; // call the Rails backend however you like to get the url & headers to upload to const result = await retrieveDirectUploadUrl({ filename, byteSize: info.size, contentType: 'image/jpeg', // this must match the value below checksum: base64, }); return result; } async function uploadFile(uri: string) { const info = retrieveDirectUpload(uri); const headers = { 'Content-Type': 'image/jpeg', // this must match the content-type of the file you're uploading ...JSON.parse(info.headers), // these are the headers coming back from `service_headers_for_direct_upload` }; const task = FileSystem.createUploadTask( info.url, uri, { headers, httpMethod: 'PUT', }, data => console.log(data.totalBytesExpectedToSend, data.totalBytesExpectedToSend), ); return task.uploadAsync(); }