How to properly serve a PDF file

后端 未结 3 637
生来不讨喜
生来不讨喜 2020-12-17 05:17

I am using .NET 3.5 ASP.NET. Currently my web site serves a PDF file in the following manner:

context.Response.WriteFile(@\"c:\\blah\\blah.pdf\");

相关标签:
3条回答
  • 2020-12-17 05:57

    You should not convert the bytes into characters, that is why it becomes "corrupted". Even though ASCII characters are stored in bytes the actual ASCII character set is limited to 7 bits. Thus, converting a byte stream with the ASCIIEncoding will effectively remove the 8th bit from each byte.

    The bytes should be written to the OutputStream stream of the Response instance.

    Instead of loading all bytes from the file upfront, which could possibly consume a lot of memory, reading the file in chunks from a stream is a better approach. Here's a sample of how to read from one stream and then write to another:

    void LoadStreamToStream(Stream inputStream, Stream outputStream)
    {
        const int bufferSize = 64 * 1024;
        var buffer = new byte[bufferSize];
    
        while (true)
        {
            var bytesRead = inputStream.Read(buffer, 0, bufferSize);
            if (bytesRead > 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
            }
            if ((bytesRead == 0) || (bytesRead < bufferSize))
                break;
        }
    }
    

    You can then use this method to load the contents of your file directly to the Response.OutputStream

    LoadStreamToStream(fileStream, Response.OutputStream);
    

    Better still, here's a method opening a file and loading its contents to a stream:

    void LoadFileToStream(string inputFile, Stream outputStream)
    {
        using (var streamInput = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
        {
            LoadStreamToStream(streamInput, outputStream);
            streamInput.Close();
        }
    }
    
    0 讨论(0)
  • 2020-12-17 06:01

    You may also need to set the ContentType by doing something like this:

    Response.ContentType = "application/octet-stream";
    
    0 讨论(0)
  • 2020-12-17 06:02

    Building upon Peter Lillevold's answer, I went and just made some extension methods for his above functions.

    public static void WriteTo(this Stream inputStream, Stream outputStream)
    {
        const int bufferSize = 64 * 1024;
        var buffer = new byte[bufferSize];
    
        while (true)
        {
            var bytesRead = inputStream.Read(buffer, 0, bufferSize);
            if (bytesRead > 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
            }
            if ((bytesRead == 0) || (bytesRead < bufferSize)) break;
        }
    }
    
    public static void WriteToFromFile(this Stream outputStream, string inputFile)
    {
        using (var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
        {
            inputStream.WriteTo(outputStream);
            inputStream.Close();
        }
    }
    
    0 讨论(0)
提交回复
热议问题