PDF在应用程序本地运行时打开,在推送到开发服务器时不会打开

本文关键字:开发 服务器 应用程序 运行时 PDF | 更新日期: 2023-09-27 18:30:02

我有一个网格,它列出了另一个表中每个记录的上传文档。当我在网格中单击"查看"时,当应用程序在我的本地机器上时,它会毫无问题地从sql server打开pdf。当我把它推到开发服务器上并点击查看时,它会冻结应用程序一分钟左右。我不太确定这里发生了什么,尽管我怀疑这个方法可能是试图在服务器上而不是我的机器上运行pdf?

protected void UploadedDocumentsRadGrid_ItemCommand(object sender, GridCommandEventArgs e)
{
    if(e.CommandName == "ViewDoc")
    {
        if(e.Item is GridDataItem)
        {
            GridDataItem item = (GridDataItem)e.Item;
            var doc = from d in db.UploadedDocuments
                      where d.ID.ToString() == item["ID"].Text
                      select d;
            foreach(var Doc in doc)
            {
                string filePath = Path.GetTempFileName();
                File.Move(filePath, Path.ChangeExtension(filePath, ".pdf"));
                filePath = Path.ChangeExtension(filePath, ".pdf");
                File.WriteAllBytes(filePath, Doc.DocumentData.ToArray());
                OpenPDFFile(filePath);
            }
        }
    }
}
protected void OpenPDFFile(string filePath)
{
    using(System.Diagnostics.Process p = new System.Diagnostics.Process())
    {
        p.StartInfo = new System.Diagnostics.ProcessStartInfo(filePath);
        p.Start();
        p.WaitForExit();
        try
        {
            File.Delete(filePath);
        }
        catch { }
    }
}

进一步解释:

此应用程序允许用户将扫描的文档上载到SQL表中。如果用户需要查看上传的文档,他们应该能够在网格中单击该文档,然后该文档应该在本地机器上打开。我这样做不对吗?

更新:

现在一切都按需要运转。非常感谢Sunil为我提供的代码。我确实不得不将SQL连接更改为LINQ到SQL语句,这没什么大不了的。最终代码如下:

    var doc = from d in db.UploadedDocuments
              where d.ID.ToString() == Session["ID"].ToString()
              select d;
    foreach (var Doc in doc)
    {
        byte[] bytes = Doc.DocumentData.ToArray();
        this.Page.Response.Buffer = true;
        this.Page.Response.Charset = "";
        this.Page.Response.ClearContent();
        if (this.Page.Request.QueryString["download"] == "1")
        {
            this.Page.Response.AppendHeader("Content-Disposition", "attachment; filename=PDF.pdf");
        }
        this.Page.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        this.Page.Response.ContentType = "application/pdf";
        this.Page.Response.BinaryWrite(bytes);
        this.Page.Response.Flush();
        this.Page.Response.End();

PDF在应用程序本地运行时打开,在推送到开发服务器时不会打开

根据Paddy的建议,您需要从代码中设置mime类型。

在您的情况下,如果filePath指向像c:'myfiles'pdfs'abc.pdf这样的文件,则可以使用第一个代码片段,但如果它的filePath像~/files/abc.pdf,即pdf文件存储在网站根文件夹下的某个位置,则使用第二个代码片段。我不知道你为什么要在浏览器中打开文件后删除它。

当filePath是绝对路径或UNC路径时

protected void OpenPDFFile(string filePath)
{
       //set the appropriate ContentType.
        Response.ContentType = "Application/pdf";
       //write the file to  http content output stream.
        Response.WriteFile(filePath);
        Response.End();
}

当filePath是像~/mypfile.pdf这样的web路径时

protected void OpenPDFFile(string filePath)
{
       //set the appropriate ContentType.
        Response.ContentType = "Application/pdf";
       //get the absolute file path
       filePath = MapPath(filePath);
       //write the file to  http content output stream.
        Response.WriteFile(filePath);
        Response.End();
}

更新1

根据您的说法,您希望从远程web服务器删除用户本地计算机上的文件,因为web应用程序代码在远程服务器中执行。这是绝对不可能的,即使是这样,这也将是一个巨大的安全风险,因为远程计算机将控制最终用户的计算机。因此,我建议您遵循网络应用程序中的常规做法,将文件流式传输到最终用户的计算机。

若数据库中存储了文件,则可以使用下面的代码在最终用户的计算机上打开pdf文件。最终用户会点击你的gridview中的文件链接,然后执行服务器端的链接点击代码,将pdf文件流式传输到用户的计算机。请注意,gridview中文件的链接应该是一个链接按钮,其命令参数等于上载的uploadfileId列值。

我假设在您的数据库中有一个表Uploads,它有这些列——UploadId, FileData, FileName, FileContentType,UploadId是一个自动递增的主键

GridView中链接的标记,单击后将下载pdf

   <asp:TemplateField ItemStyle-HorizontalAlign="Center">
        <ItemTemplate>
            <asp:LinkButton ID="lnkViewPdfFile" runat="server" Text="View Pdf" OnClick="ViewPdfFile" CommandArgument='<%# Eval("UploadId") %>'></asp:LinkButton>
        </ItemTemplate>
    </asp:TemplateField>

点击上面文件的事件后面代码中的链接按钮

protected void ViewPdfFile(object sender, EventArgs e)
 {         
        int uploadId = int.Parse(btn.CommandArgument);
        byte[] bytes;
        string fileName, contentType;
        string conString = ConfigurationManager.ConnectionStrings["appdatabase"].ConnectionString;
        using (SqlConnection con = new SqlConnection(conString))
        {
            using (SqlCommand cmd = new SqlCommand())
            {
                cmd.CommandText = "SELECT FileName, FileData, ContentType FROM Uploads WHERE UploadId=@uploadId";
                cmd.Parameters.AddWithValue("@uploadId", uploadId);
                cmd.Connection = con;
                con.Open();
                using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    sdr.Read();
                    bytes = (byte[])sdr["FileData"];
                    contentType = sdr["ContentType"].ToString();
                    fileName = sdr["FileName"].ToString();
                }
                con.Close();
            }
        }
        context.Response.Buffer = true;
        context.Response.Charset = "";
        if (context.Request.QueryString["download"] == "1")
        {
            context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
        }
        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.Response.ContentType = "application/pdf";
        context.Response.BinaryWrite(bytes);
        context.Response.Flush();
        context.Response.End();
 }

您正在编写服务器端代码。你可能会发现你的网络服务器上有很多打开的PDF(尽管你的通用"捉迷藏"处理可能掩盖了那里的任何问题)。您需要使用适当的mime类型将文件数据流式传输到客户端。

它在本地工作,因为您的web服务器与开发时打开浏览器的机器相同。

很难完全复制您的代码,因为您正在打开多个PDF文件-您可能会发现最好在另一个窗口中打开这些文件,而不是像这样直接回发。