Bir C # MVC web sitesinde sanal dosyaları nasıl destekleneceğini

oy
21

Kullanıcıların zaman onların çağrı özgü alt alan daha sonra web sitesi web sitelerini gösterecektir web sitesine kendi html kodunu yükleyebilir tümünü yakalama web sitesi yapıyorum.

ekleri ile html kodu web sitesinin içindeki bir alt dizine yüklendiğinde olsun:

SITE #1
~/sites/test1/index.html
~/sites/test1/images/logo.png

SITE #2
~/sites/test2/index.html
~/sites/test2/images/logo.png

Yani aşağıdaki URL'ler kullanarak bu dosyaları arayabilirsiniz:

SITE #1
http://test1.mydomain.com/index.html
http://test1.mydomain.com/images/logo.png

SITE #2
http://test2.mydomain.com/index.html
http://test2.mydomain.com/images/logo.png

Yani ne oldu da var olmayan bir dosya isteği çalıştığınızda algılar global.asax iç hata işleyicisi yapmak olduğunu, dolayısıyla web sitesi talep:

protected void Application_Error()
{
    // Get the subdomain requested
    var subdomain = Request.Url.Authority.Split(new char[] { '.', ':' }).FirstOrDefault();

    // Get the directory info about the requested subdomain
    DirectoryInfo info = new DirectoryInfo(Server.MapPath(~/ + subdomain));

    // Check if subdomain is not empty and exists
    if (!string.IsNullOrEmpty(subdomain) && info.Exists)
    {
        // Get the requested filename
        var filename = Request.Url.PathAndQuery.Split(new char[] { '?' }).FirstOrDefault();

        // If the root is requested change to index.html
        if (filename == /) filename = /index.html;

        // Translate requested filename to server path
        var fullname = Server.MapPath(~/sites/ + subdomain + filename);

        // Respond the file
        ResponseFile(fullname);
    }
    else
    {
        // Subdomain not found so end the request
        Response.End();
    }
}

public void ResponseFile(string fullname)
{
    Response.Clear();

    System.IO.Stream oStream = null;

    try
    {
        // Open the file
        oStream =
            new System.IO.FileStream
                (path: fullname,
                mode: System.IO.FileMode.Open,
                share: System.IO.FileShare.Read,
                access: System.IO.FileAccess.Read);

        // **************************************************
        Response.Buffer = false;

        // Setting the ContentType
        Response.ContentType = MimeMapping.GetMimeMapping(fullname);

        // Get the length of the file 
        long lngFileLength = oStream.Length;

        // Notify user (client) the total file length
        Response.AddHeader(Content-Length, lngFileLength.ToString());
        // **************************************************

        // Total bytes that should be read
        long lngDataToRead = lngFileLength;

        // Read the bytes of file
        while (lngDataToRead > 0)
        {
            // The below code is just for testing! So we commented it!
            //System.Threading.Thread.Sleep(200);

            // Verify that the client is connected or not?
            if (Response.IsClientConnected)
            {
                // 8KB
                int intBufferSize = 8 * 1024;

                // Create buffer for reading [intBufferSize] bytes from file
                byte[] bytBuffers =
                    new System.Byte[intBufferSize];

                // Read the data and put it in the buffer.
                int intTheBytesThatReallyHasBeenReadFromTheStream =
                    oStream.Read(buffer: bytBuffers, offset: 0, count: intBufferSize);

                // Write the data from buffer to the current output stream.
                Response.OutputStream.Write
                    (buffer: bytBuffers, offset: 0,
                    count: intTheBytesThatReallyHasBeenReadFromTheStream);

                // Flush (Send) the data to output
                // (Don't buffer in server's RAM!)
                Response.Flush();

                lngDataToRead =
                    lngDataToRead - intTheBytesThatReallyHasBeenReadFromTheStream;
            }
            else
            {
                // Prevent infinite loop if user disconnected!
                lngDataToRead = -1;
            }
        }
    }
    catch { }
    finally
    {
        if (oStream != null)
        {
            //Close the file.
            oStream.Close();
            oStream.Dispose();
            oStream = null;
        }
        Response.Close();
        Response.End();
    }
}

Yukarıdaki kod /index.html dosyası için çalışır, ancak 404 Application_Error işleyicisi ateş olmaz çünkü /images/logo.png için çalışmaz. Öğrendiğim arama ve saçımı çekerek bir sürü sonra bu özelliği yukarıda .net 4.0 ve başladı. Ama geri dönmek istemiyorum, ben düzgün bu çözmek için nasıl bilmek istiyorum.

Oluştur 08/02/2018 saat 19:48
kullanıcı
Diğer dillerde...                            


2 cevaplar

oy
3

Uygulama hatası ulaşılmasını beklemek geç boru hattında az. Tek yolu özel işleyici oluşturmaktır ve özel bir rota kullanarak sanal dosya işleyicisi, bu talepleri harita algılamak için. Bu belki de bir yol yapım öngörülebilir bir düzen kullanarak sanal dosyalara bağlantılar oluşturmak gerektiği anlamına gelir gibi / SpecialFiles /:

routes.Add(new Route("SpecialFiles/{*path}", new SomeFileHandler()));

Ayrıca aa denetleyici eylem bu harita ve eylem URL / sorgu dizesi ayrıştırmak ve bir dosya yanıtı dönelim başladı.

Her iki yaklaşım böyle "paylaşılan dosya" bağlantıları diğer sistemlerde görülen benzer dosyaya erişmek için gereken son derece tesadüfi belirteci gibi çeşitli parametreleri ile bir rota belirlemenizi sağlar. Sen Özellikle dosya uzantılarında eşleşecek şekilde rotayı yapılandırabilirsiniz. seçenekleri oldukça çeşitlidir. Tıpkı diğer yolu gibi, sen değişkenlere yolunun farklı parçalarını itebilir, ya da işleyici veya harekete geçmek ve manuel olarak ayrıştırmak kez sadece Request doğrudan URL'yi erişebilirsiniz.

Cevap 08/02/2018 saat 19:56
kaynak kullanıcı

oy
0

AaronLS sayesinde, tüm istekleri yakalamak istiyorum özel bir işleyici nasıl aramaya başladı. Çok kötü bulmak o kadar kolay değildi.

Her şeyden önce, size web.config güncelleyerek tüm dosyaları işlemek istediğiniz IIS bilgilendirmek gerekir:

<system.webServer>
    <httpErrors existingResponse="PassThrough" />
    <modules runAllManagedModulesForAllRequests="true">
        <remove name="FormsAuthentication"/>
    </modules>
</system.webServer>

(Bunu bilmiyorum httpErrors existingResponse = "PassThrough" olabilirdi, gerçekten ihtiyaç vardır denedim önceki bazı çözüm)

Sonra Kendi özel işleyicisi yapmak ve routeconfig bunu kurmak için gerekli:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // So my users can still login
        routes.MapRoute(
            name: "Account",
            url: "Account/{action}/{id}",
            defaults: new { controller = "Account", action = "Index", id = UrlParameter.Optional }
        );

        // For the upload controller to work
        routes.MapRoute(
            name: "Upload",
            url: "Upload/{action}/{id}",
            defaults: new { controller = "Upload", action = "Index", id = UrlParameter.Optional }
        );

        // And finally registrating my custom handler
        routes.Add(new Route("{*path}", new CustomRouteHandler()));

        // This was the original routeconfig
        //routes.MapRoute(
        //    name: "Default",
        //    url: "{controller}/{action}/{id}",
        //    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        //);
    }
}
public class CustomRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new CustomHttpHandler();
    }
}
public class CustomHttpHandler : IHttpHandler
{
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
    public void ProcessRequest(HttpContext context)
    {
        // Get the subdomain requested
        var subdomain = context.Request.Url.Authority.Split(new char[] { '.', ':' }).FirstOrDefault();

        // Get the directory info about the requested subdomain
        DirectoryInfo info = new DirectoryInfo(context.Server.MapPath("~/Websites/" + subdomain));

        // Check if subdomain is not empty and exists
        if (!string.IsNullOrEmpty(subdomain) && info.Exists)
        {
            // Get the requested filename
            var filename = context.Request.Url.PathAndQuery.Split(new char[] { '?' }).FirstOrDefault();

            // If the root is requested change to index.html
            if (filename == "/") filename = "/index.html";

            // Translate requested filename to server path
            var fullname = context.Server.MapPath("~/Websites/" + subdomain + filename);

            // Respond the file
            ResponseFile(context, fullname);
        }
        else
        {
            // Subdomain not found so end the request
            context.Response.End();
        }
    }
    public void ResponseFile(HttpContext context, string fullname)
    {
        // Clear the response buffer
        context.Response.Clear();

        System.IO.Stream oStream = null;

        try
        {
            // Open the file
            oStream =
                new System.IO.FileStream
                    (path: fullname,
                    mode: System.IO.FileMode.Open,
                    share: System.IO.FileShare.Read,
                    access: System.IO.FileAccess.Read);

            // **************************************************
            context.Response.Buffer = false;

            // Setting the ContentType
            context.Response.ContentType = MimeMapping.GetMimeMapping(fullname);

            // Get the length of the file 
            long lngFileLength = oStream.Length;

            // Notify user (client) the total file length
            context.Response.AddHeader("Content-Length", lngFileLength.ToString());
            // **************************************************

            // Total bytes that should be read
            long lngDataToRead = lngFileLength;

            // Read the bytes of file
            while (lngDataToRead > 0)
            {
                // Verify that the client is connected or not?
                if (context.Response.IsClientConnected)
                {
                    // 8KB
                    int intBufferSize = 8 * 1024;

                    // Create buffer for reading [intBufferSize] bytes from file
                    byte[] bytBuffers =
                        new System.Byte[intBufferSize];

                    // Read the data and put it in the buffer.
                    int intTheBytesThatReallyHasBeenReadFromTheStream =
                        oStream.Read(buffer: bytBuffers, offset: 0, count: intBufferSize);

                    // Write the data from buffer to the current output stream.
                    context.Response.OutputStream.Write
                        (buffer: bytBuffers, offset: 0,
                        count: intTheBytesThatReallyHasBeenReadFromTheStream);

                    // Flush (Send) the data to output
                    // (Don't buffer in server's RAM!)
                    context.Response.Flush();

                    lngDataToRead =
                        lngDataToRead - intTheBytesThatReallyHasBeenReadFromTheStream;
                }
                else
                {
                    // Prevent infinite loop if user disconnected!
                    lngDataToRead = -1;
                }
            }
        }
        catch (Exception e)
        {
        }
        finally
        {
            if (oStream != null)
            {
                //Close the file.
                oStream.Close();
                oStream.Dispose();
                oStream = null;
            }
            context.Response.Close();
            context.Response.End();
        }
    }
}
Cevap 27/03/2018 saat 09:38
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more