Azure Function下载SharePoint Online文件时的FileContentResult编码异常问题
我在使用HTTP触发的Azure Function从SharePoint Online下载文件时遇到了编码问题,文件可成功下载但显示损坏,无法识别文件类型。以下是相关代码:
DownloadFile方法代码
public dynamic DownloadFile(Guid fileUniqueId) { const string apiUrl = "{0}/_api/web/GetFileById('{1}')/$value"; try { var fileInfo = GetFileInfo(fileUniqueId); if (string.IsNullOrEmpty(_sharepointSiteUrl)) return null; string api = string.Format(apiUrl, _sharepointSiteUrl, fileUniqueId.ToString()); string response = new TokenHelper().GetAPIResponse(api); if (string.IsNullOrEmpty(response)) return null; return new { fileInfo.FileName, Bytes = Encoding.UTF8.GetBytes(response) }; } catch (Exception ex) { throw ex; } }
Azure Function触发代码
string guidString = req.Query["id"]; if (!Guid.TryParse(guidString, out var fileId)) return new BadRequestResult(); var fileManager = new FileManager(); dynamic fileData = fileManager.DownloadFile(fileId); if (null == fileData) return new NotFoundResult(); var contentType = (((string)fileData.FileName).ToUpper().EndsWith(".PNG") || ((string)fileData.FileName).ToUpper().EndsWith(".JPEG") || ((string)fileData.FileName).ToUpper().EndsWith(".JPG")) ? "image/jpeg" : "application/octet-stream"; return new FileContentResult(fileData.Bytes, contentType) { FileDownloadName = fileData.FileName };
问题原因与修复方案
核心问题
SharePoint的$value接口返回的是文件原始二进制流,但你当前代码把二进制数据先转换成UTF-8字符串,再转回字节数组——这个过程会彻底破坏非文本文件(图片、文档等)的字节结构:二进制数据中大量不符合UTF-8编码规则的字节序列会被替换成占位符(如�),最终导出的字节数组和原始文件完全不一致,导致文件损坏。
修复步骤
修改TokenHelper的GetAPIResponse方法,让它直接返回
byte[],跳过字符串转换,保留原始二进制数据:public byte[] GetAPIResponse(string apiUrl) { using (var client = new HttpClient()) { // 此处添加你的身份验证逻辑(如设置Authorization请求头) var response = client.GetAsync(apiUrl).Result; response.EnsureSuccessStatusCode(); return response.Content.ReadAsByteArrayAsync().Result; } }更新DownloadFile方法,直接使用二进制字节数组返回:
public dynamic DownloadFile(Guid fileUniqueId) { const string apiUrl = "{0}/_api/web/GetFileById('{1}')/$value"; try { var fileInfo = GetFileInfo(fileUniqueId); if (string.IsNullOrEmpty(_sharepointSiteUrl)) return null; string api = string.Format(apiUrl, _sharepointSiteUrl, fileUniqueId.ToString()); byte[] fileBytes = new TokenHelper().GetAPIResponse(api); if (fileBytes == null || fileBytes.Length == 0) return null; return new { fileInfo.FileName, Bytes = fileBytes }; } catch (Exception ex) { throw ex; } }(可选优化)修正ContentType判断逻辑,PNG文件需匹配
image/png类型,避免浏览器识别错误:var fileName = (string)fileData.FileName; var contentType = fileName.ToUpper() switch { var name when name.EndsWith(".PNG") => "image/png", var name when name.EndsWith(".JPG") || name.EndsWith(".JPEG") => "image/jpeg", _ => "application/octet-stream" };
内容的提问来源于stack exchange,提问作者Hubert Solecki
相关产品推荐
相关产品推荐

