使用 C# 保存 Tableau API 响应中包含的 Excel 文件

Use C# to Save an Excel File Contained in a Tableau API Response

我正在尝试从 Tableau 视图下载 Excel 文件,使用基于这篇文章的片段:Downloading Files with the WebRequest and WebResponse Classes

WebResponse response = null;
Stream webStream = null;
Stream localStream   = null;
  
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);
request.Method = "GET";
request.Headers.Add("X-Tableau-Auth", token);

response = request.GetResponse();
webStream = response.GetResponseStream();

localStream = File.Create("testing.xlsx");
byte[] buffer = new Byte[1024];
int bytesRead;

int bytesProcessed = 0;
do
{
    bytesRead = webStream.Read(buffer, 0, buffer.Length);
    localStream.Write(buffer, 0, bytesRead);
    bytesProcessed += bytesRead;
} while (bytesRead > 0);

response.Close();
webStream.Close();
localStream.Close();

但是当我尝试打开 Excel 文件时,它说“不,也许它已损坏?”。响应是一个完整的 Excel 文件“准备保存”,这意味着它是使用 UTF-8 编码的。确实,如果我使用 Postman 调用,然后保存响应,保存和打开没有任何问题。

在找到我上面说的页面之前,我认为问题是因为响应是 UTF-8 而 class String 是 UTF-16。所以,我做了一些测试,从 Postman 生成的文件中获取数据,然后写入一个新文件。测试结果:确实,如果数据通过String,则保存不好。然后我尝试使用该代码,得到相同的结果:失败。我很确定这段代码没有使用任何 UTF-16 编码变量,但也许我错了。

无论如何,有谁知道我的代码有什么问题,或者指出我完成任务的正确方法吗?也就是说,要将 Tableau 报告下载到 Excel,请使用 Tableau API。

提前致谢。

除非您使用的是特别旧的 .NET 版本,否则引用 link 的是 2004 年的版本。以下代码可在 .NET 5 / C# 9 中使用,而在早期版本中仅需一些using 语句的细微调整。它针对 Tableau Online 显示,但如果我不得不猜测的话,它应该适用于最新版本的服务器。这是示例级代码,因此如果您打算经常进行此调用,我建议 following best practices for the HttpClient

//using System.IO;
//using System.Net.Http;

var token = "your-session-token";
var uri = "https://your-pod.online.tableau.com/api/.../sites/.../views/.../crosstab/excel";
var yourFile = "D:/file/test.xlsx";

using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Add("X-Tableau-Auth", token);
using var response = await client.SendAsync(request);
using FileStream outputFileStream = new FileStream(yourFile, FileMode.Create);
await response.Content.CopyToAsync(outputFileStream);

更新:如果您受限于 WebRequest 和非异步方法,您可以尝试以下方法:

var token = "your-session-token";
var uri = "https://your-pod.online.tableau.com/api/.../sites/.../views/.../crosstab/excel";
var yourFile = "D:/file/test.xlsx";

WebRequest request = WebRequest.Create(uri);
request.Method = "GET";
request.Headers.Add("X-Tableau-Auth", token);

var response = request.GetResponse();
if(((HttpWebResponse)response).StatusCode == HttpStatusCode.OK)
{
    using (Stream dataStream = response.GetResponseStream())
    using (FileStream fileStream = new FileStream(yourFile, FileMode.CreateNew))
    {
        dataStream.CopyTo(fileStream);
    }
}
response.Close();