Domanda

Ho questo codice riportato di seguito per portare gli allegati di pagina per l'utente:

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

Il problema è che tutti i file supportati funziona correttamente (jpg, gif, png, pdf, doc, ecc), ma i file .docx, quando scaricato, sono corrotti e devono essere fissati da Office al fine di essere aperto.

In un primo momento non sapevo se il problema era a decomprimere il file zip che conteneva il .docx, così invece di mettere il file di output solo nella risposta, ho salvato per primo, e il file aperto con successo, così ho conosce il problema dovrebbe essere a scrivere la risposta.

Lo sai che cosa può accadere?

È stato utile?

Soluzione

Inoltre ho incontrato questo problema ed effettivamente trovato la risposta qui: http: // www .aspmessageboard.com / showthread.php? t = 230.778

Si scopre che il formato docx deve avere Response.End () subito dopo il Response.BinaryWrite.

Altri suggerimenti

Quando si memorizza un file binario in SQL Server, tenere a mente che un file è imbottita per la boundry parola più vicino, in modo da poter potenzialmente avere un byte in più aggiunto a un file. La soluzione è quella di memorizzare le dimensioni del file originale nel db quando si memorizzano il file, e l'uso che per la lunghezza che deve essere passato alla funzione di scrittura dell'oggetto Stream. "Stream.Write (bytes (), 0, lunghezza)". Questo è il modo affidabile solo di ottenere la corretta dimensione del file, che è molto importante per Office 2007 e il backup dei file, che non consentono di caratteri in più per essere alla fine di essi (la maggior parte degli altri tipi di file come JPG di non cura).

Non si deve usare stream.GetBuffer() perché restituisce la matrice del buffer che potrebbe contenere byte inutilizzati. Utilizzare stream.ToArray() invece. Inoltre, hai provato a chiamare stream.Seek(0, SeekOrigin.Begin) prima di scrivere qualcosa?

Con i migliori saluti,
Oliver Hanappi

Per quello che vale, ho anche incontrato lo stesso problema elencato qui. Per me la questione era in realtà con il codice di caricamento non il codice per il download:

    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 questo esempio, il problema è dichiaro il arrBuffer matrice Byte con una dimensione di un byte troppo grandi. Questo byte null viene quindi salvato il file di immagine per la DB con e riprodotto su download. Il codice corretto sarebbe:

        Dim arrBuffer(FileStream.Length - 1) As Byte

Anche per il mio codice di riferimento HttpResponse è il seguente:

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

Se si utilizza l'approccio di cui sopra che utilizza response.Close (), Scaricare managers, come IE10 diranno 'non può scaricare il file', perché le lunghezze di byte non corrispondono le intestazioni. Vedere la documentazione. NON usare response.Close. MAI. Tuttavia, utilizzando il verbo CompeteRequest da sola non si spegne la scrittura di byte al flusso ouput così le applicazioni basate su XML come ad esempio Word 2007 vedrà il docx come danneggiato. In questo caso, rompere la regola di non utilizzare per Response.End. Il codice seguente risolve entrambi i problemi. I risultati possono variare.

        '*** 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: si utilizza response.Close -> si può provare con IE 10? scommetto che non funziona (i conteggi di byte non corrispondono)

Sembra tutto ok. La mia unica idea è quella di provare a chiamare Dispose sul flusso dopo aver chiamato Response.Flush anziché prima, nel caso in cui i byte non sono del tutto scritti prima del lavaggio.

Date un'occhiata a questo: scrittura MemoryStream per oggetto risposta

Ho avuto lo stesso problema e l'unica soluzione che ha funzionato per me era:

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

Ho avuto lo stesso problema, mentre provo ad aprire .docx e .xlsx documenti. Ho risolto il problema definendo la cacheability a ServerAndPrivate invece di NoCache

non è il mio metodo da chiamare documento:

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();          
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top