Πώς να υποστηρίξουν εικονικά αρχεία σε ένα δικτυακό τόπο C # MVC

ψήφοι
21

Κάνω ένα catch-all ιστοσελίδα όπου οι χρήστες μπορούν να φορτώσουν το δικό τους κώδικα HTML στην ιστοσελίδα τότε η ιστοσελίδα θα δείξει την ιστοσελίδα τους κατά την κλήση τους το συγκεκριμένο υποτομέα.

Ο κώδικας HTML με συνημμένα να έχει φορτωθεί σε ένα υποκατάλογο μέσα στον δικτυακό τόπο:

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

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

Έτσι, μπορείτε να καλέσετε αυτά τα αρχεία χρησιμοποιώντας τις ακόλουθες διευθύνσεις URL:

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

Έτσι αυτό που έκανα ήταν να κάνει χειρισμού σφαλμάτων μέσα στο Global.asax που ανιχνεύει όταν προσπαθείτε να ζητήσετε ένα αρχείο που δεν υπάρχει, ως εκ τούτου, να ζητήσει από τον δικτυακό τόπο:

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();
    }
}

Ο παραπάνω κώδικας λειτουργεί για το αρχείο «/index.html», αλλά δεν λειτουργεί για το «/images/logo.png», επειδή το 404 δεν θα απολύσει τον χειριστή Application_Error. Μετά από πολλή αναζήτηση και τραβώντας τα μαλλιά μου έξω ανακάλυψα αυτό το «χαρακτηριστικό» που ξεκίνησε από το .net 4.0 και πάνω. Αλλά δεν θέλω να πάω πίσω, θέλω να μάθω πώς να λύσει σωστά αυτό.

Δημοσιεύθηκε 08/02/2018 στις 19:48
χρήστη
Σε άλλες γλώσσες...                            


2 απαντήσεις

ψήφοι
3

Αναμονή μέχρι σφάλμα εφαρμογής είναι λίγο αργά στο στάδιο της προετοιμασίας. Ένας τρόπος είναι να δημιουργήσετε μια προσαρμοσμένη χειριστή, και χρησιμοποιώντας μια προσαρμοσμένη διαδρομή για τον εντοπισμό εικονικών αρχείων χάρτη τα αιτήματα προς το χειριστή. Αυτό σημαίνει ότι θα πρέπει να δημιουργήσετε συνδέσμους προς την εικονική αρχεία χρησιμοποιώντας ένα προβλέψιμο μοτίβο, ίσως κάνοντας μια διαδρομή, όπως / SpecialFiles /:

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

Θα μπορούσατε επίσης να χαρτογραφήσει αυτό αα δράση του ελεγκτή, και αφήστε τη δράση αναλύσει τη διεύθυνση URL / συμβολοσειράς ερωτήματος και να επιστρέψει μια απάντηση αρχείου.

Είτε προσέγγιση σας επιτρέπει να ορίσετε μια διαδρομή με διάφορες παραμέτρους, όπως είναι ένα εξαιρετικά τυχαίο δείγμα που απαιτείται για να αποκτήσετε πρόσβαση στο αρχείο παρόμοιο με το «κοινόχρηστο αρχείο» συνδέσεις δει σε άλλα συστήματα. Θα μπορούσατε να ρυθμίσετε τη διαδρομή ώστε να ταιριάζει στις ιδιαίτερες επεκτάσεις αρχείων. Οι επιλογές είναι αρκετά πλούσιο. Ακριβώς όπως και κάθε άλλη διαδρομή, μπορείτε να ωθήσει διαφορετικά κομμάτια της διαδρομής σε μεταβλητές, ή μπορείτε απλά να αποκτήσετε πρόσβαση στο URL απευθείας από την Αίτημα τη στιγμή που θα μπει στο χειριστή ή ενέργεια σας και να αναλύσει το χέρι.

Απαντήθηκε 08/02/2018 στις 19:56
πηγή χρήστη

ψήφοι
0

Χάρη στην AaronLS, άρχισα να ψάχνω πώς να κάνει μια προσαρμοσμένη χειριστή που θα καλύψουν όλα τα αιτήματα. Κρίμα που δεν ήταν τόσο εύκολο να βρεθεί.

Πρώτα απ 'όλα, θα πρέπει να ενημερώσει IIS που θέλετε να χειριστείτε όλα τα αρχεία με την ενημέρωση του web.config:

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

(Εγώ δεν το ξέρω το «Διέλευση» httpErrors existingResponse = πραγματικά χρειάζεται, θα μπορούσε να έχει κάποια προηγούμενη λύση προσπάθησα)

Τότε είχα ανάγκη να κάνω τη δική μου έθιμο χειριστή και το έστησαν στο routeconfig:

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();
        }
    }
}
Απαντήθηκε 27/03/2018 στις 09:38
πηγή χρήστη

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