Warum .docx-Dateien beschädigt werden, wenn sie von einer ASP.NET-Seite herunterzuladen?

StackOverflow https://stackoverflow.com/questions/2477564

  •  21-09-2019
  •  | 
  •  

Frage

Ich habe diese folgenden Codepage-Anhänge an den Benutzer zu bringen:

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();
}

Das Problem ist, dass alle unterstützten Dateien funktioniert (jpg, gif, png, pdf, doc, etc), aber .docx-Dateien, wenn heruntergeladen haben, sind beschädigt, und sie müssen durch Amt festgelegt, um zu geöffnet werden.

Zuerst wusste ich nicht, ob das Problem an war Dekomprimieren Sie die Zip-Datei, die die .docx enthalten, so anstatt, die Ausgabedatei nur in der Antwort, sparte ich es zuerst, und die Datei erfolgreich geöffnet, so dass ich kennen das Problem Antwort schreiben sollte.

Weißt du, was passieren kann?

War es hilfreich?

Lösung

Ich lief auch in dieses Problem und fand tatsächlich die Antwort hier: http: // www .aspmessageboard.com / showthread.php? t = 230778

Es stellt sich heraus, dass die docx-Format Bedürfnisse Response.End haben () direkt nach dem Response.BinaryWrite.

Andere Tipps

Wenn eine Binärdatei in SQL Server speichern, beachten Sie, dass eine Datei in dem nächsten Wort boundry aufgefüllt, so dass Sie möglicherweise ein zusätzliches Byte in eine Datei hinzugefügt haben. Die Lösung ist, die ursprüngliche Dateigröße in der DB zu speichern, wenn Sie die Datei speichern und verwenden, die für die Länge, dass der Bedarf an die Schreibfunktion des Stream-Objekts übergeben werden. "Stream.Write (Bytes (), 0, length)". Dies ist der einzige zuverlässige Weg, um die richtige Dateigröße des Erhaltens, die für Office 2007 und Dateien sehr wichtig ist, die es erlauben, keine zusätzlichen Zeichen am Ende von ihnen (den meisten anderen Dateitypen wie jpg do not care) zu sein.

Sie sollten nicht stream.GetBuffer() verwenden, da es die Puffer Array zurückgibt, die nicht verwendeten Bytes enthalten könnten. Verwenden stream.ToArray() statt. Außerdem haben Sie versucht stream.Seek(0, SeekOrigin.Begin) rufen, bevor etwas zu schreiben?

Die besten Grüße, Oliver Hanappi

Für das, was es wert ist, lief ich auch in das gleiche Problem hier aufgeführt. Für mich war das Problem tatsächlich mit dem Upload-Code nicht der Download-Code ein:

    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

In diesem Beispiel ist das Problem ich den Byte-Array arrBuffer mit einem Größe eines Byte zu groß erklären. Dieser Null-Byte wird dann mit dem Dateibild zu dem DB und reproduzierte den Download gespeichert. Der korrigierte Code wäre:

        Dim arrBuffer(FileStream.Length - 1) As Byte

Auch als Referenz mein HttpResponse Code lautet wie folgt:

                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()

Wenn Sie den Ansatz, über der Verwendung verwendet response.Close (), Download-Manager wie IE10 werden sagen, ‚kann Datei nicht herunterladen‘, weil die Byte-Längen nicht die Header entsprechen. Lesen Sie die Dokumentation. Sie NICHT response.Close verwenden. JE. Allerdings ist die CompeteRequest mit Verb allein nicht das Schreiben von Bytes an dem ouput Strom abgeschaltet so XML-basierten Anwendungen wie Word 2007 werden die docx als beschädigt sehen. In diesem Fall bricht die Regel nie Gebrauch Response.End. Der folgende Code löst beide Probleme. Ihre Ergebnisse können variieren.

        '*** 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: Sie response.Close verwenden -> können Sie es mit IE versuchen 10? wette, es (Match Bytezählwerte nicht) funktioniert nicht

Es sieht alles ok. Meine einzige Idee ist, den Aufruf von Dispose auf dem Strom, um zu versuchen, nachdem Response.Flush anstatt vor, nur für den Fall rief der Bytes nicht vollständig geschrieben vor dem Spülen.

Schauen Sie eine dieser: Schreiben Memory auf Antwort Objekt

Ich hatte das gleiche Problem und die einzige Lösung, die für mich gearbeitet wurde:

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

Ich hatte das gleiche Problem, während ich versuche, und XLSX-Dokumente zu öffnen .docx. Ich löse das Problem durch die Cache-Fähigkeit zu ServerAndPrivate statt NoCache definieren

Es ist meine Methode zum Aufruf Dokument:

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();          
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top