C#實現(xiàn)以文件流的形式返回本地文件或遠(yuǎn)程文件路徑
更新時間:2025年08月21日 15:49:43 作者:VipSoft
FileStream和FileInfo只能處理本地文件路徑,無法直接處理HTTP URL,所以下面小編就來和大家詳細(xì)介紹一下C#如何實現(xiàn)以文件流的形式返回本地文件或遠(yuǎn)程文件路徑吧
FileStream和FileInfo只能處理本地文件路徑,無法直接處理HTTP URL。以下是幾種實現(xiàn)遠(yuǎn)程PDF返回給前端的解決方案:
方案1:使用HttpClient下載遠(yuǎn)程文件(推薦)
[HttpGet]
public async Task<HttpResponseMessage> GetReportFile()
{
try
{
string orderNo = HttpContext.Current.Request.QueryString["orderNo"];
string filePath = "D:\\1.pdf";
if(!string.IsNullOrEmpty(orderNo))
{
filePath = "http://www.a.com/1.pdf";
// 使用HttpClient下載遠(yuǎn)程文件
using (var httpClient = new HttpClient())
{
// 設(shè)置超時時間
httpClient.Timeout = TimeSpan.FromSeconds(30);
// 下載文件內(nèi)容
var response = await httpClient.GetAsync(filePath);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsByteArrayAsync();
// 創(chuàng)建返回結(jié)果
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(content);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
{
FileName = "document.pdf"
};
return result;
}
}
else
{
// 處理本地文件
FileInfo foundFileInfo = new FileInfo(filePath);
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(fs);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
{
FileName = foundFileInfo.Name
};
return result;
}
}
catch (Exception ex)
{
logger.Error(ex, ex.Message);
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
方案2:流式傳輸(節(jié)省內(nèi)存)【推薦】
[HttpGet]
public async Task<HttpResponseMessage> GetReportFile()
{
try
{
string orderNo = HttpContext.Current.Request.QueryString["orderNo"];
string filePath = "D:\\1.pdf";
if(!string.IsNullOrEmpty(orderNo))
{
filePath = "http://www.a.com/1.pdf";
using (var httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromSeconds(30);
// 流式下載
var response = await httpClient.GetAsync(filePath, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
var stream = await response.Content.ReadAsStreamAsync();
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
{
FileName = "document.pdf"
};
return result;
}
}
else
{
// 本地文件處理...
}
}
catch (Exception ex)
{
logger.Error(ex, ex.Message);
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
方案3:添加緩存和錯誤處理
[HttpGet]
public async Task<HttpResponseMessage> GetReportFile()
{
try
{
string orderNo = HttpContext.Current.Request.QueryString["orderNo"];
string filePath = "D:\\1.pdf";
if(!string.IsNullOrEmpty(orderNo))
{
filePath = "http://www.a.com/1.pdf";
using (var httpClient = new HttpClient())
{
// 添加User-Agent頭,有些服務(wù)器需要
httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0");
httpClient.Timeout = TimeSpan.FromSeconds(30);
// 先獲取頭部信息檢查文件是否存在
var headResponse = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, filePath));
if (!headResponse.IsSuccessStatusCode)
{
return new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent("遠(yuǎn)程文件未找到")
};
}
// 獲取文件名(從Content-Disposition或URL中提?。?
string fileName = "document.pdf";
if (headResponse.Content.Headers.ContentDisposition != null)
{
fileName = headResponse.Content.Headers.ContentDisposition.FileName ?? fileName;
}
// 下載文件
var getResponse = await httpClient.GetAsync(filePath, HttpCompletionOption.ResponseHeadersRead);
getResponse.EnsureSuccessStatusCode();
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(await getResponse.Content.ReadAsStreamAsync());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
{
FileName = fileName
};
// 添加緩存頭(可選)
result.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromHours(1)
};
return result;
}
}
else
{
// 本地文件處理...
}
}
catch (HttpRequestException httpEx)
{
logger.Error(httpEx, "網(wǎng)絡(luò)請求錯誤");
return new HttpResponseMessage(HttpStatusCode.BadGateway);
}
catch (TaskCanceledException timeoutEx)
{
logger.Error(timeoutEx, "請求超時");
return new HttpResponseMessage(HttpStatusCode.RequestTimeout);
}
catch (Exception ex)
{
logger.Error(ex, ex.Message);
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
重要注意事項
- 異步方法:將方法改為
async Task<HttpResponseMessage>以支持異步操作 - 資源釋放:確保正確釋放
HttpClient和流資源 - 超時處理:為遠(yuǎn)程請求設(shè)置合理的超時時間
- 錯誤處理:添加針對網(wǎng)絡(luò)請求的特定錯誤處理
- 內(nèi)存考慮:對于大文件,使用流式傳輸避免內(nèi)存溢出
推薦使用方案2的流式傳輸,因為它內(nèi)存效率更高,特別適合處理大文件。
到此這篇關(guān)于C#實現(xiàn)以文件流的形式返回本地文件或遠(yuǎn)程文件路徑的文章就介紹到這了,更多相關(guān)C#文件流返回文件路徑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# 使用HttpClient上傳文件并附帶其他參數(shù)的步驟
這篇文章主要介紹了C# 使用HttpClient上傳文件并附帶其他參數(shù)的步驟,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-12-12
C#(WinForm) ComboBox和ListBox添加項及設(shè)置默認(rèn)選擇項
這篇文章主要介紹了C#(WinForm) ComboBox和ListBox添加項及設(shè)置默認(rèn)選擇項的的相關(guān)資料,需要的朋友可以參考下2014-07-07

