Android Kotlin中如何通过Apps Script向谷歌表格发送Zip文件
实现自定义文件(Zip/GLB等)上传至谷歌表格方案
核心思路
谷歌表格单元格无法直接存储二进制文件,正确的做法是将文件上传至Google Drive,再把Drive文件的共享链接写入表格。以下是Kotlin端(客户端)和Apps Script端(服务端)的具体实现步骤:
一、Kotlin端修改:打包文件为Zip并转Base64
先实现文件打包为Zip的工具函数,再将Zip文件转成Base64字符串(和你现有图片的处理逻辑统一),加入请求参数中:
1. 添加Zip打包与Base64编码函数
private fun zipFilesAndEncodeToBase64(files: List<File>): String? { return try { val byteArrayOutputStream = ByteArrayOutputStream() val zipOutputStream = ZipOutputStream(byteArrayOutputStream) // 遍历选中的文件,写入Zip流 files.forEach { file -> val entry = ZipEntry(file.name) zipOutputStream.putNextEntry(entry) val fileInputStream = FileInputStream(file) val buffer = ByteArray(1024) var length: Int while (fileInputStream.read(buffer).also { length = it } > 0) { zipOutputStream.write(buffer, 0, length) } fileInputStream.close() zipOutputStream.closeEntry() } zipOutputStream.close() // 转Base64(用NO_WRAP避免换行,防止服务端解码出错) Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.NO_WRAP) } catch (e: Exception) { e.printStackTrace() null } }
2. 修改上传函数,加入Zip参数
private fun startUploading() { try { val map: HashMap<String, String> = HashMap() map["instagramLink"] = binding.creatorInstaID.text.toString() map["tutorialLink"] = binding.youTubeLink.text.toString() map["detailDescription"] = binding.detailDescription.text.toString() map["coverImage"] = userImage!! // 替换selectedFiles为你实际获取用户选中文件的列表 val zipBase64 = zipFilesAndEncodeToBase64(selectedFiles) zipBase64?.let { map["productZip"] = it } ?: run { Toast.makeText(context, "打包Zip文件失败", Toast.LENGTH_SHORT).show() return } mainViewModel.saveProduct(map) } catch (e: Exception) { Toast.makeText(context, "请补全所有信息或检查文件", Toast.LENGTH_SHORT).show() } }
二、Apps Script端修改:接收Base64并存储至Drive
修改你的saveProduct函数,解码Base64为Blob,创建Drive文件并获取共享链接,最后写入表格:
function saveProduct(formData) { try { // 替换为你的谷歌表格ID const sheet = SpreadsheetApp.openById("你的表格ID").getActiveSheet(); // 解析前端传入的参数 const instagramLink = formData.instagramLink; const tutorialLink = formData.tutorialLink; const detailDescription = formData.detailDescription; const coverImageBase64 = formData.coverImage; const productZipBase64 = formData.productZip; // 处理封面图片(沿用你原有的逻辑) const coverBlob = Utilities.newBlob(Utilities.base64Decode(coverImageBase64), "image/jpeg", "封面图.jpg"); const coverFile = DriveApp.createFile(coverBlob); coverFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); const coverUrl = coverFile.getUrl(); // 处理Zip文件 const zipBlob = Utilities.newBlob(Utilities.base64Decode(productZipBase64), "application/zip", "产品文件.zip"); const zipFile = DriveApp.createFile(zipBlob); // 设置共享权限(按需调整,比如仅组织内可见) zipFile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); const zipUrl = zipFile.getUrl(); // 将所有信息写入表格新行 sheet.appendRow([instagramLink, tutorialLink, detailDescription, coverUrl, zipUrl]); return {status: "success"}; } catch (e) { console.error("上传失败:", e); return {status: "failed", message: e.toString()}; } }
关键注意事项
- 文件大小限制:Apps Script Web App单次请求上限约5MB,若Zip文件过大,需改用Google Drive Direct Upload API(需额外OAuth认证)。
- 权限配置:部署Apps Script Web App时,需设置权限为「任何人,甚至匿名」(或按需限制访问范围),否则前端请求会被拒绝。
- Base64编码一致性:Kotlin端用
Base64.NO_WRAP避免换行,确保服务端解码正常。
内容的提问来源于stack exchange,提问作者Irfan Ahamed S
相关产品推荐
相关产品推荐

