You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:40:43