我有以下代码用于将页面附件带给用户:

private void GetFile(string package, string filename)
{
    var stream = new MemoryStream();

    try
    {
        using (ZipFile zip = ZipFile.Read(package))
        {
            zip[filename].Extract(stream);
        }
    }
    catch (System.Exception ex)
    {
        throw new Exception("Resources_FileNotFound", ex);
    }

    Response.ClearContent();
    Response.ClearHeaders();
    Response.ContentType = "application/unknown";

    if (filename.EndsWith(".docx"))
    {
        Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
    }

    Response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
    Response.BinaryWrite(stream.GetBuffer());
    stream.Dispose();
    Response.Flush();
    HttpContext.Current.ApplicationInstance.CompleteRequest();
}

问题是所有受支持的文件都可以正常工作(jpg、gif、png、pdf、doc 等),但 .docx 文件在下载时已损坏,需要由 Office 修复才能打开。

起初我不知道问题是否出在解压缩包含 .docx 的 zip 文件时,因此我没有将输出文件仅放在响应中,而是先保存了它,并且文件成功打开,所以我知道问题所在应该在写回复时。

你知道会发生什么吗?

有帮助吗?

解决方案

我也遇到了这个问题,实际上找到了答案在这里: HTTP:// WWW .aspmessageboard.com / showthread.phpΔT= 230778

事实证明,所述的docx格式需要有到Response.End()的Response.BinaryWrite之后。

其他提示

当存储在SQL Server中的二进制文件,请记住,一个文件被填充到最接近的词boundry,这样你就可以潜在地添加到文件的额外的字节。解决的办法是存储在当您存储文件数据库原始文件的大小,并用它为需要传递给Stream对象的写入功能的长度。 “Stream.Write(字节(),0,长度)”。这是获得正确的文件大小,这是Office 2007和备份文件,它不允许多余的字符是他们的最后非常重要的(大多数其他文件类型,如JPG文件不关心)的唯一可靠的方法。

你不应该使用 stream.GetBuffer() 因为它返回可能包含未使用字节的缓冲区数组。使用 stream.ToArray() 反而。另外,您是否尝试过打电话 stream.Seek(0, SeekOrigin.Begin) 在写任何东西之前?

此致,
奥利弗·哈纳皮

有关它的价值,我也跑进这里列出了同样的问题。对我来说,这个问题实际上是与上传的代码不是在下载代码:

    Public Sub ImportStream(FileStream As Stream)
        'Use this method with FileUpload.PostedFile.InputStream as a parameter, for example.
        Dim arrBuffer(FileStream.Length) As Byte
        FileStream.Seek(0, SeekOrigin.Begin)
        FileStream.Read(arrBuffer, 0, FileStream.Length)
        Me.FileImage = arrBuffer
    End Sub

在这个例子中,问题是我声明字节数组arrBuffer的尺寸的一个字节太大。然后,这个空字节与文件一起保存图像数据库和下载转载。校正后的代码将是:

        Dim arrBuffer(FileStream.Length - 1) As Byte

同样对于参考我HttpResponse代码如下:

                context.Response.Clear()
                context.Response.ClearHeaders()
                'SetContentType() is a function which looks up the correct mime type
                'and also adds and informational header about the lookup process...
                context.Response.ContentType = SetContentType(objPostedFile.FileName, context.Response)
                context.Response.AddHeader("content-disposition", "attachment;filename=" & HttpUtility.UrlPathEncode(objPostedFile.FileName))
                'For reference: Public Property FileImage As Byte()
                context.Response.BinaryWrite(objPostedFile.FileImage)
                context.Response.Flush()

如果您使用上面,它使用response.Close()的办法,下载管理器,如IE10会说“无法下载文件”,因为字节长度不匹配的标头。查看文档。不要使用response.Close。 EVER。 但是,单独使用CompeteRequest动词没有字节写入关闭到输出流,以便基于XML的应用程序,如2007年WORD将看到的docx为损坏。 在这种情况下,打破规则,不要使用到Response.End。下面的代码解决了这两个问题。结果可能会不同。

        '*** transfer package file memory buffer to output stream
        Response.ClearContent()
        Response.ClearHeaders()
        Response.AddHeader("content-disposition", "attachment; filename=" + NewDocFileName)
        Me.Response.ContentType = "application/vnd.ms-word.document.12"
        Response.ContentEncoding = System.Text.Encoding.UTF8
        strDocument.Position = 0
        strDocument.WriteTo(Response.OutputStream)
        strDocument.Close()
        Response.Flush()
        'See documentation at http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx
        HttpContext.Current.ApplicationInstance.CompleteRequest() 'This is the preferred method
        'Response.Close() 'BAD pattern. Do not use this approach, will cause 'cannot download file' in IE10 and other download managers that compare content-Header to actual byte count
        Response.End() 'BAD Pattern as well. However, CompleteRequest does not terminate sending bytes, so Word or other XML based appns will see the file as corrupted. So use this to solve it.

@Cesar:您正在使用response.Close - >你可以用IE 10试一试呢?打赌它不工作(字节数不匹配)

这一切看起来OK。我唯一的想法是尝试调用Response.Flush,而不是之前后调用Dispose在你的流,以防万一字节没有完全冲洗之前写的。

看一看一个这样的:书写的MemoryStream到响应对象

我有同样的问题,只是对我工作的解决方案是:

    Response.Clear();
    Response.ContentType = "Application/msword";
    Response.AddHeader("Content-Disposition", "attachment; filename=myfile.docx");
    Response.BinaryWrite(myMemoryStream.ToArray());
    // myMemoryStream.WriteTo(Response.OutputStream); //works too
    Response.Flush();
    Response.Close();
    Response.End();

我有同样的问题,而我尝试打开的.docx和.XLSX文件。我通过定义可缓存到ServerAndPrivate代替NoCache的解决问题

有我的方法调用文件:

public void ProcessRequest(HttpContext context)

 {


       var fi = new FileInfo(context.Request.Path);
        var mediaId = ResolveMediaIdFromName(fi.Name);
        if (mediaId == null) return;

        int mediaContentId;
        if (!int.TryParse(mediaId, out mediaContentId)) return;

        var media = _repository.GetPublicationMediaById(mediaContentId);
        if (media == null) return;

        var fileNameFull = string.Format("{0}{1}", media.Name, media.Extension);
        context.Response.Clear();
        context.Response.AddHeader("content-disposition", string.Format("attachment;filename={0}", fileNameFull));            
        context.Response.Charset = "";
        context.Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);
        context.Response.ContentType = media.ContentType;
        context.Response.BinaryWrite(media.Content);
        context.Response.Flush();          
        context.Response.End();          
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top