簡體   English   中英

在ASP.NET MVC中將字節數組下載為文件

[英]Downloading a byte array as a file in asp.net mvc

我有一個字節數組,試圖將其下載為docx文件。 我允許用戶上傳多個文件並創建一個新的模型對象來存儲每個文件信息。 然后,我將編輯文件數據並向用戶返回一個新文件。 現在,我正在嘗試使用FileStreamResult從字節數組下載文件。 從我在使用FileStreamResult進行研究時所看到和閱讀的內容來看,似乎是推薦的。 這是將字節數組下載為文件的最佳方法嗎? 為什么我的上載方法返回時出現錯誤?

我的html代碼是:

<html>
<body>
    <div class="jumbotron">
        <h1>File Upload through HTML</h1>
        <form enctype="multipart/form-data" method="post" id="uploadForm" action="http://localhost:51906/api/FileUpload/Upload">
            <fieldset>
                <legend>Upload Form</legend>
                <ol>
                    <li>
                        <label>Upload File</label>
                        <input type="file" id="fileInput" name="fileInput" accept=".docx, .xml" multiple>
                    </li>
                    <li>
                        <input type="submit" value="Upload" id="submitBtn" class="btn">
                    </li>
                </ol>
            </fieldset>
        </form>
    </div>
</body>
</html>

我的控制器代碼如下:

        [HttpPost]
        public async Task<ActionResult> Upload() //Task<FileStreamResult>
        {
            if (!Request.Content.IsMimeMultipartContent())
            {   
                throw new Exception();
                return null;
            }

            var provider = new MultipartMemoryStreamProvider();
            await Request.Content.ReadAsMultipartAsync(provider);

            List<FileUpload> fileList = new List<FileUpload>();
            foreach (var file in provider.Contents) 
            {
                FileUpload f = new FileUpload //Create a new model
                {
                    fileName = file.Headers.ContentDisposition.FileName.Trim('\"'),
                    contentType = file.Headers.ContentType.MediaType,
                    fileBuffer = await file.ReadAsByteArrayAsync()                     
                };
                fileList.Add(f);

//TEMPORARY FOR TESTING DOWNLOAD
                if (f.contentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
                    final = new FileUpload
                    {
                        fileName = f.fileName,
                        contentType = f.contentType,
                        fileBuffer = f.fileBuffer
                    };
            }

            //convert(fileList);           

            Stream stream = new MemoryStream(final.fileBuffer);
            FileStreamResult fsr = new FileStreamResult(stream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
            {
                FileDownloadName = "file.docx"
            };
            return fsr;
        }

我知道直到創建流和FileStreamResult對象都可以正常工作為止的所有操作。 但是,當我運行代碼時,結果如下:

<Error>
  <Message>An error has occurred.</Message>
  <ExceptionMessage>
         The 'ObjectContent`1' type failed to serialize the response body for content type                'application/xml; charset=utf-8'.
  </ExceptionMessage>
  <ExceptionType>
     System.InvalidOperationException
  </ExceptionType>
  <StackTrace/>
  <InnerException>
     <Message>An error has occurred.</Message>
     <ExceptionMessage>
      Type 'System.Web.Mvc.FileStreamResult' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types.
     </ExceptionMessage>
     <ExceptionType>
     System.Runtime.Serialization.InvalidDataContractException
     </ExceptionType>
     <StackTrace>   
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type)
       at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)
       at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
       at System.Runtime.Serialization.DataContractSerializer.GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType)
       at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
       at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
       at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
       at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph)
       at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)
       at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
       at System.Web.Http.WebHost.HttpControllerHandler.  
       <WriteBufferedResponseContentAsync>d__14.MoveNext()
     </StackTrace>
  </InnerException>
</Error>

使用屬性DataContractAttribute標記FileUpload類的fileName,contentType,fileBuffer成員

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM