如何在Apex/Salesforce中实现带删除按钮的分片多部分文件上传
基于JavaScript实现Salesforce分片上传的完整实现方案
前置准备
首先完成Salesforce端配置,避免权限或跨域问题:
- 配置Salesforce CORS规则,允许前端域名访问
- OAuth2授权获取有效访问Token,确保账号拥有
Create ContentVersion、Delete ContentVersion权限 - 使用不低于v48.0的Salesforce REST API版本
核心实现代码
1. 前端DOM结构
<!-- 文件上传控件 --> <input type="file" id="fileUpload" multiple> <!-- 进度条 --> <div style="width: 100%; height: 8px; background: #eee; margin: 10px 0;"> <div id="uploadProgress" style="height: 100%; width: 0%; background: #2e84fa;"></div> </div> <!-- 已上传文件列表 --> <ul id="uploadedFileList"></ul>
2. JavaScript逻辑实现
首先定义可配置参数,满足自定义分片大小需求:
// 可自定义分片大小,示例为5MB,可根据需求调整 const CHUNK_SIZE = 5 * 1024 * 1024; const SF_API_VERSION = 'v58.0'; const SF_INSTANCE_URL = '你的Salesforce实例域名'; let accessToken = '你的OAuth授权Token'; let uploadedFiles = []; // 存储已上传文件信息
分片上传核心逻辑
const fileUploadDom = document.getElementById('fileUpload'); const progressDom = document.getElementById('uploadProgress'); const fileListDom = document.getElementById('uploadedFileList'); fileUploadDom.addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; const totalChunks = Math.ceil(file.size / CHUNK_SIZE); let uploadedSize = 0; progressDom.style.width = '0%'; try { // 第一步:创建Salesforce分片上传会话 const sessionRes = await fetch(`${SF_INSTANCE_URL}/services/data/${SF_API_VERSION}/connect/files/users/me`, { method: 'POST', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ title: file.name, fileType: file.name.split('.').pop(), totalParts: totalChunks }) }); const sessionData = await sessionRes.json(); const uploadSessionId = sessionData.id; // 第二步:逐个上传分片 for (let i = 0; i < totalChunks; i++) { const start = i * CHUNK_SIZE; const end = Math.min(start + CHUNK_SIZE, file.size); const chunk = file.slice(start, end); await fetch(`${SF_INSTANCE_URL}/services/data/${SF_API_VERSION}/connect/files/users/me/${uploadSessionId}/parts/${i+1}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/octet-stream' }, body: chunk }); uploadedSize += chunk.size; // 更新进度条 progressDom.style.width = `${Math.round((uploadedSize / file.size) * 100)}%`; } // 第三步:合并分片完成上传 const completeRes = await fetch(`${SF_INSTANCE_URL}/services/data/${SF_API_VERSION}/connect/files/users/me/${uploadSessionId}`, { method: 'POST', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' } }); const completedFile = await completeRes.json(); // 保存已上传文件信息,渲染到列表 const fileInfo = { id: completedFile.contentDocumentId, name: file.name, size: file.size }; uploadedFiles.push(fileInfo); renderFileList(); } catch (err) { console.error('上传失败:', err); progressDom.style.width = '0%'; } });
已上传文件列表渲染&删除逻辑
// 渲染已上传文件列表 function renderFileList() { fileListDom.innerHTML = ''; uploadedFiles.forEach((file, index) => { const li = document.createElement('li'); li.innerHTML = ` <span>${file.name} (${Math.round(file.size / 1024 / 1024)}MB)</span> <button data-index="${index}" class="delete-btn">删除</button> `; fileListDom.appendChild(li); }); // 绑定删除事件 document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', async (e) => { const index = e.target.dataset.index; const fileId = uploadedFiles[index].id; // 调用Salesforce接口删除文件 await fetch(`${SF_INSTANCE_URL}/services/data/${SF_API_VERSION}/sobjects/ContentDocument/${fileId}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${accessToken}` } }); // 更新本地列表 uploadedFiles.splice(index, 1); renderFileList(); }); }); }
功能对应说明
- 支持文件分片上传:通过
file.slice切割文件,调用Salesforce分块上传接口逐片上传,支持大文件上传避免超时 - 已上传文件展示:上传完成后将文件信息存入本地数组,调用
renderFileList动态渲染到DOM - 删除已上传文件:每个文件项绑定删除事件,调用Salesforce删除接口后同步更新本地列表
- 自定义分片大小:修改
CHUNK_SIZE变量即可调整分片大小,建议不低于1MB、不超过30MB - 上传进度指示:每成功上传一个分片后计算已上传占比,实时更新进度条宽度
内容的提问来源于stack exchange,提问作者Ravi Shah
相关产品推荐
相关产品推荐

