如何使用Salesforce上的JSZip从Google云端硬盘下载多个文件作为.zip

时间:2016-11-19 10:54:46

标签: javascript google-drive-api salesforce apex jszip

案例: 在Salesforce平台上,我使用Google Drive来存储配置了 Apex Google Drive API Framework 的文件(此案例的图片)。因此Google Drive API会处理authToken等问题。我可以在我的应用程序中上传和浏览图像。在我的情况下,我想选择多个文件并将其下载到一个zip文件中。到目前为止,我正在尝试使用JSZipFileSaver库。使用下面相同的代码我可以使用正确的响应标题压缩和下载存储在其他位置的多个文件,但由于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.如果我点击此链接,文件就会开始下载。

有没有办法配置GDrive以启用响应头:Access-Control-Allow-Origin: *Access-Control-Allow-Origin: https://*/mydomain.com某种方式或者我只需要使用其他东西,可能是服务器端压缩?现在我使用的是Apex Google Drive API提供的下载链接(如下所示: 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

此链接由GRDrive连接器处理,因此如果我只是在浏览器中输入它,则下载图像。但是,对于使用JS的多次下载,我收到了CORS错误。

3 个答案:

答案 0 :(得分:2)

我认为此功能尚不支持。如果您从Drive API检查Download Files guide,则不会提及一次下载多个文件。那是因为您必须为每个文件制作单独的API请求。这已在此SO thread中得到确认。

但选择的多个文件将转换为单个zip文件并下载单个zip文件,这可以通过google drive API实现。那么如何将它们转换为单个Zip文件?请告诉我。

答案 1 :(得分:2)

据我所知,只需下载所有文件并将它们存储在临时目录位置,然后将该目录添加到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;
    }

答案 2 :(得分:0)

我之前发布的代码有效。忘了发布解决方案。 我没有使用内容集线器链接,而是开始使用直接链接到Google云端硬盘并解决了CORS问题。仍然不确定CORS是否可以在Salesforce方面以某种方式解决。尝试了不同的设置,没有运气。 直接下载链接到GDrive在我的情况下工作正常。我唯一需要改变的是GDrive文件ID的前缀。