views:

554

answers:

2

I'm working on a web app and need to stream various files. I can do pdfs, images, and older Office documents. However, when I try to do with 2007 documents, it breaks. Here is my code:

    Response.Buffer = true;
    Response.Clear();
    Response.ClearContent();
    Response.ClearHeaders();
    switch (FileExtension.ToLower())
    {
        case "pdf":
            Response.ContentType = "application/pdf";
            break;
        case "doc":
            Response.ContentType = "application/msword";
            break;
        case "docx":
            Response.ContentType = "application/vnd.ms-word.document.12";
            break;
        case "xls":
            Response.ContentType = "application/vnd.ms-excel";
            break;
        case "xlsx":
            Response.ContentType = "application/vnd.ms-excel.12";
            break;
        default:
            Response.ContentType = "image/jpeg";
            break;
    }
    Response.BinaryWrite(buffer);

The error that I get is:

An invalid character was found in text content. Error processing resource 'http://DomainName/GetFile.aspx...

PK

Any suggestions?

+2  A: 

According to a brief web search, the correct mime types for word and excel are:

application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

http://www.bram.us/2007/05/25/office-2007-mime-types-for-iis/

Edit:

The following simplified sample works for me. It is different from yours in that it uses a generic handler instead of a web form (which is more appropriate for something like this anyway).

To test it, make sure there is an excel 2007 file named Book1.xlsx in the top level folder of the application.

DownloadSpreadsheet.ashx:

<%@ WebHandler Language="C#" Class="DownloadSpreadsheetHandler" %>

using System;
using System.Web;
using System.IO;

public class DownloadSpreadsheetHandler: IHttpHandler {

    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        string path = context.Server.MapPath("~/Book1.xlsx");
        using (FileStream spreadsheet = File.OpenRead(path))
        {
            CopyStream(spreadsheet, context.Response.OutputStream);
        }
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

    private static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        while (true)
        {
            int read = input.Read(buffer, 0, buffer.Length);
            if (read <= 0)
                return;
            output.Write(buffer, 0, read);
        }
    }

}
Erv Walter
Tried this and it is slightly better. I am at least getting the open/save/cancel dialog box. However, if I click open on a docx file, I get nothing but a blank html page. If I click save on the dialog box, save it to file, then open it, I click through some error messages and then get the right file. For xlsx files, if I save then open, I get the same thing as docx, ie a few error messages then it opens. However, if I click open on the xlsx file, I have to click through a few errors, then excel opens, but instead of the data, I have my login page
Kevin
I added sample code that works.
Erv Walter
That did it. Why it works like this and not the other way is beyond me, but I'm too busy to care at the moment.
Kevin
A: 

For csv format files that we want Excel to be used to open, we are using: Response.ContentType = "application/msexcel";

Perhaps we get away with this because it is not a true xls file, however.

Nij