如何在 Salesforce 上使用 JSZip 从 Google Drive 下载多个文件为 .zip

How to download multiple files from Google Drive as .zip using JSZip on Salesforce

案例: 在 Salesforce 平台上,我使用 Google Drive 来存储文件(本例中的图像),并配置了 Apex Google Drive API Framework。所以 Google Drive API 处理 authToken 等等。我可以在我的应用程序中上传和浏览图像。在我的例子中,我想 select 多个文件并将它们下载到一个 zip 文件中。到目前为止,我正在尝试使用 JSZipFileSaver 库来做到这一点。使用下面的相同代码 我可以通过适当的响应 header 压缩和下载存储在其他地方的多个文件,但由于 CORS 错误不能从 GDrive 下载。

https://xxx.salesforce.com/contenthub/download/XXXXXXXXXX%3Afile%XXXXXX_XXXXXXXXX. No'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://xxx.visual.force.com' is therefore not allowed access. 如果我只点击这个 link,文件开始下载。

有什么方法可以配置 GDrive 以启用响应 header: Access-Control-Allow-Origin: *Access-Control-Allow-Origin: https://*/mydomain.com 或者我只需要使用其他东西,也许是服务器端压缩?现在我正在使用 Apex Google Drive API 提供的下载 link(看起来像这样: https://xxx.salesforce.com/contenthub/download/XXXXXXXXXXX%3Afile%XXXXXXXX),当用作 src="fileURL" 或直接粘贴到浏览器时,它工作正常。 GDrive连接器添加'accesToken'等。

我的代码:

//ajax request to get files using JSZipUtils
let urlToPromise = (url) =>{
    return new Promise(function(resolve, reject) {
        JSZipUtils.getBinaryContent(url, function (err, data) {
            if(err) {
            reject(err);
            } else {
            resolve(data);
            }
        });
    });
};

this.downloadAssets = () => {
let zip = new JSZip();
//here 'selectedAssets' array of objects each of them has 'assetFiles'
//with fileURL where I have url. Download and add them to 'zip' one by one
for (var a of this.selectedAssets){
    for (let f of a.assetFiles){
        let url = f.fileURL;                
        let name = a.assetName + "." + f.fileType;
        let filename = name.replace(/ /g, ""); 
        zip.file(filename, urlToPromise(url), {binary:true});                                    
    }
}
//generate zip and download using 'FileSaver.js'    
zip.generateAsync({type:"blob"})
    .then(function callback(blob) {
     saveAs(blob, "test.zip");
    });       
};

我还尝试将 let url = f.fileURL 更改为 GDrive 连接器添加的 let url = f.fileURL + '?alt=media';&access_token=CURRENT_TOKEN

这个 link 由 GRDrive 连接器处理,所以如果我只是在浏览器中输入它,它就会下载图像。但是,对于使用 JS 进行的多次下载,我遇到了 CORS 错误。

我认为尚不支持此功能。如果您检查 Download Files guide from Drive API, there's no mention of downloading multiple files at once. That's because you have to make individual API requests for each file. This is confirmed in this SO thread.

但是选择的多个文件被转换为单个 zip 文件并下载单个 zip 文件,这可以使用 google 驱动器 API。那么如何将它们转换成单个 Zip 文件呢?请告诉我。

根据我的说法,只需下载所有文件并将它们存储在临时目录位置,然后将该目录添加到 zip 文件并将该 zip 文件存储到物理设备。

 public Entity.Result<Entity.GoogleDrive> DownloadMultipleFile(string[] fileidList)
    {
        var result = new Entity.Result<Entity.GoogleDrive>();
        ZipFile zip = new ZipFile();

        try
        {
            var service = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Download File",
            });

            FilesResource.ListRequest listRequest = service.Files.List();
            //listRequest.PageSize = 10;
            listRequest.Fields = "nextPageToken, files(id, name, mimeType, fullFileExtension)";

            IList<File> files = listRequest.Execute().Files;

            if (files != null && files.Count > 0)
            {
                foreach (var fileid in fileidList)
                {
                    foreach (var file in files)
                    {
                        if (file.Id == fileid)
                        {                                
                                result.Data = new Entity.GoogleDrive { FileId = fileid };
                                FilesResource.GetRequest request = service.Files.Get(fileid);
                                request.ExecuteAsync();
                                var stream = new System.IO.FileStream(HttpContext.Current.Server.MapPath(@"~\TempFiles") + "\" + file.Name, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                                request.MediaDownloader.ProgressChanged += (IDownloadProgress progress) =>
                                {
                                    switch (progress.Status)
                                    {
                                        case DownloadStatus.Downloading:
                                            {
                                                break;
                                            }
                                        case DownloadStatus.Completed:
                                            {
                                                break;
                                            }
                                        case DownloadStatus.Failed:
                                            {
                                                break;
                                            }
                                    }
                                };
                                request.Download(stream);
                                stream.Close();
                                break;
                            }                                
                        }   
                    }

            }
            zip.AddDirectory(HttpContext.Current.Server.MapPath(@"~\TempFiles"), "GoogleDrive");
            string pathUser = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
            string pathDownload = System.IO.Path.Combine(pathUser, "Downloads");
            zip.Save(pathDownload + "\GoogleDrive.zip");
            System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(HttpContext.Current.Server.MapPath(@"~\TempFiles"));
            foreach (var file in di.GetFiles())
            {
                file.Delete();
            }

            result.IsSucceed = true;
            result.Message = "File downloaded suceessfully";
        }
        catch (Exception ex)
        {
            result.IsSucceed = false;
            result.Message = ex.ToString();
        }
        return result;
    }

我之前发布的代码有效。忘了post一个解决方案。 我不再使用内容中心 link,而是直接使用 link 到 Google 驱动器,CORS 问题已解决。仍然不确定 CORS 是否可以在 Salesforce 方面以某种方式解决。尝试了不同的设置但没有成功。 在我的情况下,直接下载 link 到 GDrive 就可以了。我唯一需要更改的是 GDrive 文件 ID 的前缀。