如何从 HttpInputStream 获取 docx 文件的字节数组?
Posted
技术标签:
【中文标题】如何从 HttpInputStream 获取 docx 文件的字节数组?【英文标题】:How do I get a byte array from HttpInputStream for a docx file? 【发布时间】:2013-10-14 12:06:01 【问题描述】:我正在使用这篇文章中第一个答案的方法:How to create byte array from HttpPostedFile,但由于某种原因它不适用于 .docx 文件。
//viewmodel.File is HttpPostedFileBase
byte[] fileData;
using (var binaryReader = new BinaryReader(viewModel.File.InputStream))
fileData = binaryReader.ReadBytes(viewModel.File.ContentLength);
在 .docx 文件上 fileData
显示为 byte[0]
,但它适用于 pdf、excel 文件 (xlsx)、2007 年前的 word 文件 (doc) 和图像(即值大于零)。保存到数据库,fileData为0x
。
更新 我的 web.config 配置了
<httpRuntime targetFramework="4.5" maxRequestLength="102400" />
这适用于大于 4MB 的 xslx 文件,但不适用于小于 80KB 的 docx 文件。
更新 2 我可以使用此处说明的方法来填充 fileData:http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload.postedfile.aspx
byte[] fileData = new byte[viewModel.File.ContentLength];
viewModel.File.InputStream.Read(fileData, 0, viewModel.File.ContentLength);
但如果我将该字节数组保存到数据库并尝试写入文件,则它已严重损坏。在这种情况下保存到数据库中看起来像0x00000000000000000000000...
更新 3 这是整个控制器方法,尽管我认为没有必要查看整个内容:
[HttpPost]
public ActionResult SaveChangeFile(AttachmentFormViewModel viewModel)
if (viewModel.File == null)
return Json(new success = false, message = "No file was found, please select a file and try again." , "text/x-json",
JsonRequestBehavior.DenyGet);
try
//Validate that the right kind of File has been uploaded
OperationResponse response = _attachmentProcessor.ValidateAttachmentContentType(viewModel.File, (ChangeFileTypeEnum)viewModel.FileType);
if (!response.IsSuccess)
return Json(new success = response.IsSuccess, message = response.Message , "text/x-json", JsonRequestBehavior.DenyGet);
UpdateProjectFromCostCalculatorRequest projectValues = null;
Workbook workbook = null;
Document document = null;
if (_attachmentProcessor.IsWorkbook(viewModel.File))
workbook = new Workbook(viewModel.File.InputStream);
if (_attachmentProcessor.IsDocument(viewModel.File))
document = new Document(viewModel.File.InputStream);
var filename = Path.GetFileName(viewModel.File.FileName);
//if cost calc, validate that the values are correct and update related project
switch ((ChangeFileTypeEnum)viewModel.FileType)
case ChangeFileTypeEnum.CostCalculator:
response = _attachmentProcessor.ValidateCostCalculator(workbook, filename);
if (response.IsSuccess)
projectValues = _attachmentProcessor.GetDataFromCostCalculator(workbook);
break;
case ChangeFileTypeEnum.DataValidation:
response = _attachmentProcessor.ValidateDataValidation(workbook);
break;
case ChangeFileTypeEnum.WorkPaper:
response = _attachmentProcessor.ValidateWorkPaper(document);
break;
//return error message if any of the validations above failed
if (!response.IsSuccess)
return Json(new success = response.IsSuccess, message = response.Message , "text/x-json", JsonRequestBehavior.DenyGet);
//get the file from the stream and put into a byte[] for saving the database
byte[] fileData;
using (var binaryReader = new BinaryReader(viewModel.File.InputStream))
fileData = binaryReader.ReadBytes(viewModel.File.ContentLength);
var file = new ChangeFile
ChangeRequestID = viewModel.ChangeRequestId,
ChangeFileTypeID = viewModel.FileType,
File = fileData,
Filename = filename,
ContentType = viewModel.File.ContentType,
CreatedBy = User.UserNameWithoutDomain(),
UpdatedBy = User.UserNameWithoutDomain(),
CreatedDate = DateTime.Now,
UpdatedDate = DateTime.Now
;
_changeRequestService.SaveChangeFile(file);
var log = new ChangeFileImportLog CreatedDate = DateTime.Now ;
switch ((ChangeFileTypeEnum)viewModel.FileType)
case ChangeFileTypeEnum.CostCalculator:
var project = _changeRequestService.GetChangeProjectByPsrs(file.ChangeRequestID, projectValues.PsrsNumber);
if (project != null)
_attachmentProcessor.UpdateChangeProjectWithProjectValues(project, projectValues);
log.NumberOfErrors = 0;
log.NumberOfSegmentChanges = 0;
log.NumberOfWarnings = 0;
else
log.NumberOfWarnings = 1;
log.Warnings =
String.Format(
"There is no project on this Change Request with PSRS \"0\". If there was, the new cost would be updated with \"1:C0\"",
projectValues.PsrsNumber, projectValues.Cost);
break;
case ChangeFileTypeEnum.DataValidation:
log = _attachmentProcessor.CreateChangeSegmentsFromDataValidation(workbook, file.ChangeRequestID, file.ChangeFileID, User);
break;
case ChangeFileTypeEnum.WorkPaper:
log = _attachmentProcessor.UpdateChangeProjectsFromWorkPaper(document, file.ChangeRequestID, file.ChangeFileID,
User);
break;
log.CreatedBy = User.UserNameWithoutDomain();
log.CreatedDate = DateTime.Now;
log.UpdatedBy = User.UserNameWithoutDomain();
log.UpdatedDate = DateTime.Now;
_changeRequestService.SaveChangeFileImportLog(log, file.ChangeFileID);
_changeRequestService.Commit();
return Json(new success = response.IsSuccess, message = response.Message , "text/x-json", JsonRequestBehavior.DenyGet);
catch (Exception ex)
return Json(new success = false, message = String.Format("A system error was encountered: 0", ex) , "text/x-json", JsonRequestBehavior.DenyGet);
【问题讨论】:
docx 文件的处理方式不应与任何其他文件类型有任何不同。 没有理由发生这种情况。 “空白”是什么意思?文件数据为空吗?并且没有抛出异常? 如果其他文件正常工作,文件可能大于允许的上传大小。请参阅此帖子 ***.com/questions/288612/…,以配置该文件大小。 @neo 并不是文件太大,我们说的文件有 71KB,而我的 web.config 有<httpRuntime targetFramework="4.5" maxRequestLength="102400" />
@Vivek 好问题,我更新了我的问题
【参考方案1】:
事实证明,由于我已经在使用流(请参阅问题中的控制器方法),当我尝试保存它时它是空的。
我不确定为什么我在使用 docx 而不是 xlsx 时会遇到这种情况,因为它们在保存之前都已消耗了 Streams。我的猜测是这与 Aspose.Cells 和 Aspose.Words 实现的差异有关。
无论如何,我将流上的位置设置回 0,并且它起作用了。
//viewmodel.File is HttpPostedFileBase
viewModel.File.InputStream.Position = 0; //<-----This fixed it!
byte[] fileData;
using (var binaryReader = new BinaryReader(viewModel.File.InputStream))
fileData = binaryReader.ReadBytes(viewModel.File.ContentLength);
【讨论】:
以上是关于如何从 HttpInputStream 获取 docx 文件的字节数组?的主要内容,如果未能解决你的问题,请参考以下文章
类型“System.Web.HttpInputStream”未标记为可序列化
Swift2.0:如何通过 do try catch 获取返回值和错误