10

I am using the method from the first answer in this post: How to create byte array from HttpPostedFile but it doesn't work for .docx files for some reason.

//viewmodel.File is HttpPostedFileBase

byte[] fileData;
using (var binaryReader = new BinaryReader(viewModel.File.InputStream))
{
    fileData = binaryReader.ReadBytes(viewModel.File.ContentLength);
}

On .docx files fileData shows as {byte[0]}, but it works with pdfs, excel files (xlsx), pre 2007 word files (doc), and images (i.e. the value is greater than zero). Saved to the database, the fileData is 0x.

How do I get a byte array from HttpInputStream for a docx file?

UPDATE
My web.config is configured with

<httpRuntime targetFramework="4.5" maxRequestLength="102400" />

This is working with xslx files bigger than 4MB but docx files less than 80KB are not.

UPDATE 2
I can get fileData to populate using the method explained here: 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);

But if I saved that byte array to the database and try to write a file, it is severely corrupt. Saved to the database in this case it looks like 0x00000000000000000000000...

UPDATE 3
Here is the whole controller method, though I don't think seeing the whole thing is necessary:

    [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);

        }
    }
Community
  • 1
  • 1
wilsjd
  • 2,178
  • 2
  • 23
  • 37
  • 1
    A docx file should not be treated any differently than any other file type. – Trevor Elliott Oct 07 '13 at 19:28
  • No reason for this to happen. What do you mean "blank"? is filedata null? and no exceptions thrown? – Vivek Oct 07 '13 at 19:30
  • It's likely that the file is larger than the allowed upload size if other files are working. See this post, http://stackoverflow.com/questions/288612/how-to-increase-the-max-upload-file-size-in-asp-net, to configure that file size. – Mike Perrenoud Oct 07 '13 at 19:30
  • @neo It isn't that the files are too big, we're talking 71KB for some of these and my web.config has `` – wilsjd Oct 07 '13 at 19:32
  • @TrevorElliott that's what I was thinking as well, but posts like this make me think differently: http://stackoverflow.com/questions/18243668/what-is-wrong-with-this-binary-file-transfer-corrupting-docx-files – wilsjd Oct 07 '13 at 19:34
  • troubleshoot step: create a .txt file, rename to .docx, upload-save-download/write to file and see if that behaves any differently – Moho Oct 07 '13 at 20:24
  • also, show entire controller method please – Moho Oct 07 '13 at 20:25
  • The .txt file renamed to .docx seems to be similar - it comes back corrupted. – wilsjd Oct 07 '13 at 20:31
  • @TrevorElliott let be clear - I don't want to treat it differently and have no intention too. I would rather have one method for pulling bytes. – wilsjd Oct 07 '13 at 20:37
  • Good call @Moho, earlier in the method I had consumed the stream. – wilsjd Oct 08 '13 at 00:13

1 Answers1

12

Turns out that since I am using the stream already (see the controller method in the question), it is empty when I tried to save it.

I am not sure why I experienced this with docx and not xlsx since they both have their Streams consumed before the save. My guess is it has something to do with the differences in the Aspose.Cells and Aspose.Words implementations.

Regardless, however, I set the position on the stream back to 0, and it worked.

//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);
}
wilsjd
  • 2,178
  • 2
  • 23
  • 37