【问题标题】:ASP.NET Downloadable Image Files?ASP.NET 可下载图像文件?
【发布时间】:2013-05-24 16:26:16
【问题描述】:

我在这个网站上没有 apache 支持,但我需要能够只允许在某个目录中下载图像。我怎样才能做到这一点?这个站点只有 ASP.NET 支持,这让我很生气!注意到这个链接:How to download files in mvc3?,但不知道该把代码放在哪里,或者即使那里的代码对我有任何帮助。

任何帮助将不胜感激!起点什么的……

有没有办法可以在 HTML 中做到这一点?例如,将下载链接设置为指向一个 html 文件,HTML 文件会在该文件中抓取图像文件并使其本身可下载?

到目前为止,我在一个名为 default.asp 的文件中有以下 ASP 代码

开始下载就好了,但它下载的是一个空文件 (download.jpg)。如何将以下代码指向要下载的实际图像文件?

<%@ Language=VBScript %>
<%  Option Explicit

Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition", "attachment; filename=" + "download.jpg"

%>

即使在同一目录中,我也有一个名为“download.jpg”的文件,但它从不下载实际图像。它会下载一个 90 字节的空图像文件。

我什至没有运气尝试过:

<%@ Language=VBScript %>
<%  Option Explicit

Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition","attachment; filename=07awardee.png"
Response.TransmitFile Server.MapPath("~/images/07awardee.png")
Response.End

%>

是的,我在服务器根目录的 images/07awardee.png 甚至在 default.asp 所在的文件夹根目录中都有 07awardee.png 文件。阿格!这里给出了什么?该文件现在有点大了 392 字节,但它仍然不能作为图像文件读取......我一直在搜索互联网,这应该可以工作,但没有!这可能是什么问题?

【问题讨论】:

    标签: asp.net http-headers imagedownload


    【解决方案1】:

    带有 Request.End 的 .aspx 页面会引发 ThreadAbortException,这对服务器性能不利(其中太多甚至会导致服务器崩溃)。所以你要避免这种情况。 http://weblogs.asp.net/hajan/archive/2010/09/26/why-not-to-use-httpresponse-close-and-httpresponse-end.aspx

    我处理这个问题的方法是使用 HttpHandler (.ashx) 并使用它来提供可下载的图像文件。我使用了你的一些代码,因为我的实现是在 C# 中并且有更多的代码(包括图像缩放选项等):

    //<%@ WebHandler Language="VB" Class="DownloadImage" %> // uncomment this line!
    
    Public Class DownloadImage : Implements IHttpHandler
      Protected EnabledTypes() As String = New String() {".jpg", ".gif", ".png"}
    
      Public Sub ProcessRequest(ByVal context As HttpContext) _
        Implements IHttpHandler.ProcessRequest
        Dim request = context.Request
        If Not String.IsNullOrEmpty(request.QueryString("file")) Then
          Dim path As String = context.Server.MapPath(request.QueryString("file"))
          Dim file As System.IO.FileInfo = New System.IO.FileInfo(path)
          If file.Exists And EnabledTypes.Contains(file.Extension.ToLower()) Then
            context.Response.Clear()
            context.Response.AddHeader("Content-Disposition", _
                "attachment; filename=" & file.Name)
            context.Response.AddHeader("Content-Length", file.Length.ToString())
            context.Response.ContentType = "application/octet-stream"
            context.Response.WriteFile(file.FullName) 
          Else
            context.Response.ContentType = "plain/text"
            context.Response.Write("This file does not exist.") 
          End If
        Else
          context.Response.Write("Please provide a file to download.")
        End If
      End Sub
    
      Public ReadOnly Property IsReusable() As Boolean _
            Implements IHttpHandler.IsReusable
        Get
            Return True
        End Get
      End Property
    End Class
    

    确保您对图像文件实施检查,否则您会遇到潜在的安全问题。 (用户可以下载存储数据库密码的web.config)

    链接会变成:

    <a href="/DownloadImage.ashx?file=/images/logo.gif">Download image</a>
    

    【讨论】:

    • 'Contains' is not a member of 'System.Array'
    • 好的,我稍微更改了您的代码,因为它在 VB 中无法正确处理数组。 Contains 仅适用于 C#!但是我决定使用你的 httphandler 实现,所以我想你应该得到这个。感谢您使用 httphandler 并删除 Response.End,干杯:)
    • Array.Contains 使用 Linq 在 .NET 中工作,它是一个扩展函数。尝试添加Imports System.Linq
    【解决方案2】:

    您应该清除标题并提供正确的标题和内容类型

    Response.Clear()
    Response.AppendHeader("Content-Disposition", "attachment; filename=somefilename")
    Response.ContentType = "image/jpeg"
    Response.TransmitFile(Server.MapPath("/xyz.jpg"));
    Response.End();
    

    【讨论】:

    • 这应该在 C# 中吗?如果是这样,我需要在此位之前添加&lt;%@ Language=C# %&gt; 行以使该语法正常工作。我要测试一下……马上回来,让你知道它是否有效。想知道Server.MapPath("/xyz.jpg") 是否链接到相对于default.asp 文件所在位置的文件?或者它是否链接到相对于站点根目录 (mydomain.com) 的文件?
    • 这不起作用,我每次都下载一个损坏的 330 字节文件。该文件确实存在。我需要在Web.config 中进行更改以使其正常工作吗?我必须添加一个类还是什么?另外,您的语法错误。您缺少分号。
    • 所有浏览器都试过了吗?这可能是浏览器的问题..由于您正在下载损坏的文件,因此最好响应。写入文件路径并与实际文件路径进行比较以查看它们是否相同。
    • 谢谢,通过我的回答找到了合适的解决方案。
    【解决方案3】:

    天哪,我摇滚。这是完成的方式。创建一个名为 download.aspx 的文件,并在其中输入以下代码:

    <%@ Page language="vb" runat="server" explicit="true" strict="true" %>
    <script language="vb" runat="server">
    Sub Page_Load(Sender As Object, E As EventArgs)
        Dim strRequest As String = Request.QueryString("file")
        If strRequest <> "" AND strRequest.EndsWith(".jpg") OR strRequest.EndsWith(".jpeg") OR strRequest.EndsWith(".png") OR strRequest.EndsWith(".gif") OR strRequest.EndsWith(".pdf") OR strRequest.EndsWith(".doc") OR strRequest.EndsWith(".docx") OR strRequest.EndsWith(".bmp") Then
            Dim path As String = Server.MapPath(strRequest)
            Dim file As System.IO.FileInfo = New System.IO.FileInfo(path)
            If file.Exists Then
                Response.Clear()
                Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name)
                Response.AddHeader("Content-Length", file.Length.ToString())
                Response.ContentType = "application/octet-stream"
                Response.WriteFile(file.FullName)
                Response.End
            Else
                Response.Write("This file does not exist.")
            End If
        Else
            Response.Write("You do not have permission to download this file type!")
        End If
    End Sub
    </script>
    

    现在,当您想要下载文件(任何文件)时,只需像这样链接它:

    <a href="download.aspx?file=/images/logo.gif">Download the logo image</a>
    

    这就是她写的全部内容!

    【讨论】:

    • 一定要保护自己不提供禁区文件...例如,download.aspx?file=~/web.config 或 download.aspx?file=../../ ../secretfile.txt。见owasp.org/index.php/Top_10_2013-A4
    • 谢谢,仅允许某些文件类型的更新答案。现在应该没问题了!
    猜你喜欢
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 2016-01-10
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多