Asp.Net MVC এ যে কোনও ধরণের ফাইল ডাউনলোড করুন ফাইলের রেজাল্ট ব্যবহার করে?


228

আমি আমার কাছে এটি প্রস্তাব দিয়েছিলাম যে আমার Asp.Net MVC অ্যাপ্লিকেশন থেকে ব্যবহারকারীদের ফাইল ডাউনলোড করার অনুমতি দেওয়ার জন্য আমার ফাইলআরসাল্ট ব্যবহার করা উচিত। তবে এর একমাত্র উদাহরণ আমি খুঁজে পেতে পারি ইমেজ ফাইলগুলির সাথে সর্বদা করণীয় (বিষয়বস্তুর ধরণের চিত্র / জেপিগ উল্লেখ করে)।

তবে আমি যদি ফাইলের ধরণটি জানতে না পারি? আমি চাই যে ব্যবহারকারীরা আমার সাইটের ফাইলারি থেকে যে কোনও ফাইল ডাউনলোড করতে পারবেন।

আমি এটি করার একটি পদ্ধতি পড়েছি ( কোডের জন্য পূর্ববর্তী পোস্টটি দেখুন ), এটি আসলে একটি কাজ বাদ দিয়ে খুব ভাল কাজ করে: সেভ হিসাবে ডায়ালগটিতে যে ফাইলটি আসে সেটির নাম আন্ডারস্কোর সহ ফাইলের পথ থেকে সংক্ষিপ্ত হয় ( folder_folder_file.ext)। এছাড়াও, লোকেদের মনে হয় যে আমি বাইনারি কনটেন্টারসাল্ট খুঁজে পেয়েছি এমন কাস্টম ক্লাসটি ব্যবহার না করে আমার কোনও ফাইলসোল্ট ফিরে দেওয়া উচিত।

এমভিসিতে এমন ডাউনলোড করার "সঠিক" উপায়টি কি কেউ জানেন?

সম্পাদনা: আমি উত্তরটি পেয়েছি (নীচে), তবে কেবল ভেবেছি যদি অন্য কেউ আগ্রহী হয় তবে আমার সম্পূর্ণ কার্য কোড পোস্ট করা উচিত:

public ActionResult Download(string filePath, string fileName)
{
    string fullName = Path.Combine(GetBaseDir(), filePath, fileName);

    byte[] fileBytes = GetFile(fullName);
    return File(
        fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}

byte[] GetFile(string s)
{
    System.IO.FileStream fs = System.IO.File.OpenRead(s);
    byte[] data = new byte[fs.Length];
    int br = fs.Read(data, 0, data.Length);
    if (br != fs.Length)
        throw new System.IO.IOException(s);
    return data;
}

12
আপনি যা করছেন তা বরং বিপজ্জনক। আপনি কার্যকরভাবে ব্যবহারকারীদের আপনার সার্ভার থেকে এমন কোনও ফাইল ডাউনলোড করতে মঞ্জুরি দিচ্ছেন যা কার্যকরকারী ব্যবহারকারী অ্যাক্সেস করতে পারে।
পল ফ্লেমিং

1
সত্য - ফাইলের পথটি সরিয়ে ফেলা এবং অ্যাকশনারসুল্টের শরীরে এটি পেরেক করা কিছুটা নিরাপদ হবে। কমপক্ষে সেই পথে তাদের কেবলমাত্র একটি নির্দিষ্ট ফোল্ডারে অ্যাক্সেস রয়েছে।
shubniggurath

2
এমন কোনও সরঞ্জাম রয়েছে যা আপনাকে এই জাতীয় সম্ভাব্য বিপজ্জনক ফাঁকগুলি খুঁজে পেতে দেয়?
ডেভিড

আমি দেখতে পেলাম যে স্ট্যাকওভারফ্লো.comResponse.ContentType = MimeMapping.GetMimeMapping(filePath);
ইয়ু ইয়ং জিয়ান

আপনি ক্লায়েন্ট পক্ষ থেকে কি ব্যবহার করছেন?
ফ্রেইঙ্কিবি

উত্তর:


425

আপনি কেবল জেনেরিক অকটেট-স্ট্রিম MIME প্রকারটি নির্দিষ্ট করতে পারেন:

public FileResult Download()
{
    byte[] fileBytes = System.IO.File.ReadAllBytes(@"c:\folder\myfile.ext");
    string fileName = "myfile.ext";
    return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}

4
ঠিক আছে, আমি চেষ্টা করে দেখতে পারি, তবে বাইট [] অ্যারেতে কী যায়?
অ্যান্ডার্স

3
কিছু মনে করবেন না, আমি মনে করি আমি এটি খুঁজে পেয়েছি। আমি ফাইলের নাম (পুরো পথ) একটি ফাইল স্ট্রিমে এবং তারপরে একটি বাইট অ্যারেতে পড়েছি এবং তারপরে এটি একটি কবজির মতো কাজ করেছে! ধন্যবাদ!
অ্যান্ডার্স

5
এটি কেবল প্রবাহিত করতে পুরো ফাইলটিকে মেমরিতে লোড করে; বড় ফাইলগুলির জন্য, এটি হোগ। আরও ভাল সমাধান হ'ল নীচেরটি যা প্রথমে মেমরিতে ফাইল লোড করতে হয় না।
এইচ ব্ল্যাকর্বি

13
যেহেতু এই উত্তরটি প্রায় পাঁচ বছরের পুরানো, হ্যাঁ। আপনি যদি খুব বড় ফাইল পরিবেশন করতে এটি করছেন তবে করবেন না। যদি সম্ভব হয় তবে একটি পৃথক স্ট্যাটিক ফাইল সার্ভার ব্যবহার করুন যাতে আপনি নিজের অ্যাপ্লিকেশন থ্রেডগুলি বেঁধে রাখেন না বা 2010 থেকে এমভিসিতে যুক্ত হওয়া ফাইলগুলি সরবরাহ করার জন্য অনেকগুলি নতুন কৌশল। । ReadAllBytesএকটি সম্পাদনায় বছর পরে যুক্ত করা হয়েছিল। কেন এটি আমার দ্বিতীয় সবচেয়ে উত্তেজিত উত্তর? আচ্ছা ভালো.
ইয়ান হেনরি

10
এই ত্রুটিটি পাওয়া:non-invocable member "File" cannot be used like a method.
এ-শারাবানী

105

এমভিসি কাঠামো এটিকে স্থানীয়ভাবে সমর্থন করে। System.Web.MVC.Controller.File নিয়ামক দ্বারা একটি ফাইল ফিরে যাওয়ার পদ্ধতি প্রদান করে নাম / স্ট্রিম / অ্যারে

উদাহরণস্বরূপ, ফাইলটিতে ভার্চুয়াল পথ ব্যবহার করে আপনি নিম্নলিখিতটি করতে পারেন।

return File(virtualFilePath, System.Net.Mime.MediaTypeNames.Application.Octet,  Path.GetFileName(virtualFilePath));

36

আপনি যদি নেট ফ্রেমওয়ার্ক 4.5 ব্যবহার করছেন তবে আপনি নিজের ফাইলের জন্য মাইম টাইপ পেতে মাইম্যাপিং.গেটমাইমম্যাপিং (স্ট্রিং ফাইলনাম ) ব্যবহার করুন। এইভাবে আমি আমার ক্রিয়ায় এটি ব্যবহার করেছি।

return File(Path.Combine(@"c:\path", fileFromDB.FileNameOnDisk), MimeMapping.GetMimeMapping(fileFromDB.FileName), fileFromDB.FileName);

এটি মাইম ম্যাপিংটি দুর্দান্ত হ'ল, তবে রান টাইমে ফাইলের ধরণটি কী তা নির্ধারণের জন্য এটি কোনও প্রক্রিয়া নয়?
মোহাম্মদ নুরাল্ডিন

@ মোহাম্মদনোরাল্ডিন ​​এটি "অনুমেয়" নয়, ফাইল এক্সটেনশান বা এর মতো কোনও কিছুর উপর ভিত্তি করে একটি সাধারণ ম্যাপিং টেবিল রয়েছে। সার্ভার এটি সব স্ট্যাটিক ফাইলের জন্য করে, এটি ধীর হয় না।
আল কেপ

13

ফিল হ্যাকের একটি দুর্দান্ত নিবন্ধ রয়েছে যেখানে তিনি একটি কাস্টম ফাইল ডাউনলোড অ্যাকশন ফলাফলের ক্লাস তৈরি করেছিলেন। আপনার কেবলমাত্র ফাইলটির ভার্চুয়াল পথ এবং নামটি সংরক্ষণ করতে হবে specify

আমি এটি একবার ব্যবহার করেছি এবং আমার কোডটি এখানে।

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Download(int fileID)
        {
            Data.LinqToSql.File file = _fileService.GetByID(fileID);

            return new DownloadResult { VirtualPath = GetVirtualPath(file.Path),
                                        FileDownloadName = file.Name };
        }

আমার উদাহরণে আমি ফাইলগুলির দৈহিক পথটি সংরক্ষণ করছিলাম তাই আমি এই সহায়ক সহায়ক পদ্ধতিটি ব্যবহার করেছি - যা আমি কোথাও পেয়েছি মনে করতে পারছি না - এটি ভার্চুয়াল পথে রূপান্তর করতে

        private string GetVirtualPath(string physicalPath)
        {
            string rootpath = Server.MapPath("~/");

            physicalPath = physicalPath.Replace(rootpath, "");
            physicalPath = physicalPath.Replace("\\", "/");

            return "~/" + physicalPath;
        }

ফিল হ্যাকের নিবন্ধ থেকে নেওয়া পুরো ক্লাসটি এখানে

public class DownloadResult : ActionResult {

    public DownloadResult() {}

    public DownloadResult(string virtualPath) {
        this.VirtualPath = virtualPath;
    }

    public string VirtualPath {
        get;
        set;
    }

    public string FileDownloadName {
        get;
        set;
    }

    public override void ExecuteResult(ControllerContext context) {
        if (!String.IsNullOrEmpty(FileDownloadName)) {
            context.HttpContext.Response.AddHeader("content-disposition", 
            "attachment; filename=" + this.FileDownloadName)
        }

        string filePath = context.HttpContext.Server.MapPath(this.VirtualPath);
        context.HttpContext.Response.TransmitFile(filePath);
    }
}

1
ঠিক আছে, হ্যাঁ, আমি সেই নিবন্ধটিও দেখেছি, তবে আমি যে নিবন্ধটি ব্যবহার করেছি (তার আগের পোস্টের রেফারেন্সটি দেখুন) তার মতোই কাজটি করা দেখে মনে হচ্ছে, এবং তিনি নিজেকে পৃষ্ঠার শীর্ষে বলেছিলেন যে কাজের অংশটি উচিত নয় ' টি আর দরকার পড়বে না কারণ: "নতুন আপডেট: এই কাস্টম অ্যাকশনারসাল্টের আর দরকার নেই কারণ এএসপি.নেট এমভিসি এখন বাক্সে একটি অন্তর্ভুক্ত করেছে।" তবে দুর্ভাগ্যক্রমে, এটি কীভাবে ব্যবহার করা হবে সে সম্পর্কে তিনি আর কিছু বলেন না।
অ্যান্ডার্স

@ মানাফআবুরাস, যদি আপনি কোডটি ঘনিষ্ঠভাবে পড়েন তবে আপনি দেখতে পাবেন এটি প্রকৃতপক্ষে ভার্চুয়াল পাথকে শারীরিক পথে রূপান্তরিত করে ( Server.MapPath(this.VirtualPath)) সুতরাং এটি পরিবর্তন ছাড়াই সরাসরি গ্রহণ করা একটি বাচ্চার নিষ্পাপ। আপনার এমন একটি বিকল্প তৈরি করা উচিত PhysicalPathযা শেষ পর্যন্ত যা প্রয়োজন তা হ'ল এবং আপনি যা সংরক্ষণ করছেন তা গ্রহণ করুন। এটি অনেক বেশি নিরাপদ হবে কারণ আপনি একটি অনুমান করেছেন যে শারীরিক পথ এবং আপেক্ষিক পথটি একই হবে (মূলকে বাদ দিয়ে)। ডেটা ফাইলগুলি প্রায়শই অ্যাপ_ডাটা সংরক্ষণ করা হয়। এটি আপেক্ষিক পথ হিসাবে অ্যাক্সেসযোগ্য নয়।
পল ফ্লেমিং

গেট ভার্চুয়ালপথ দুর্দান্ত .... খুব দরকারী। ধন্যবাদ!
জেভি রেডলার

6

ইয়ান হেনরিকে ধন্যবাদ !

আপনি যদি এমএস এসকিউএল সার্ভার থেকে ফাইল পেতে চান তবে সমাধানটি এখানে।

public FileResult DownloadDocument(string id)
        {
            if (!string.IsNullOrEmpty(id))
            {
                try
                {
                    var fileId = Guid.Parse(id);

                    var myFile = AppModel.MyFiles.SingleOrDefault(x => x.Id == fileId);

                    if (myFile != null)
                    {
                        byte[] fileBytes = myFile.FileData;
                        return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, myFile.FileName);
                    }
                }
                catch
                {
                }
            }

            return null;
        }

কোথায় AppModel হয় EntityFrameworkমডেল ও MyFiles উপহার টেবিল আপনার ডাটাবেস হবে। FileData হয় varbinary(MAX)মধ্যে MyFiles টেবিল।


2

এটির সহজ ডিরেক্টরি ফাইলের নামের সাথে ডিরেক্টরিপথে আপনার শারীরিক পথ দিন

public FilePathResult GetFileFromDisk(string fileName)
{
    return File(directoryPath, "multipart/form-data", fileName);
}

ক্লায়েন্ট পক্ষ সম্পর্কে কি, এই পদ্ধতি কল? আপনি কী ডায়লগ হিসাবে সেভ দেখাতে চান তা বলুন?
ফ্রেনকিবি

0
   public ActionResult Download()
        {
            var document = //Obtain document from database context
    var cd = new System.Net.Mime.ContentDisposition
    {
        FileName = document.FileName,
        Inline = false,
    };
            Response.AppendHeader("Content-Disposition", cd.ToString());
            return File(document.Data, document.ContentType);
        }

-1

যদি (string.IsNullOrWhiteSpace (fileName)) সামগ্রী ফিরে আসে ("ফাইলের নাম উপস্থিত নেই");

        var path = Path.Combine(your path, your filename);

        var stream = new FileStream(path, FileMode.Open);

        return File(stream, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);

-4

গেটফাইলে ফাইলটি বন্ধ করা উচিত (বা এটির ব্যবহারের মধ্যে এটি খোলার)। তারপরে আপনি ফাইলটি বাইটে রূপান্তর করার পরে মুছতে পারেন - ডাউনলোডটি সেই বাইট বাফারে হবে।

    byte[] GetFile(string s)
    {
        byte[] data;
        using (System.IO.FileStream fs = System.IO.File.OpenRead(s))
        {
            data = new byte[fs.Length];
            int br = fs.Read(data, 0, data.Length);
            if (br != fs.Length)
                throw new System.IO.IOException(s);
        }
        return data;
    }

সুতরাং আপনার ডাউনলোড পদ্ধতিতে ...

        byte[] fileBytes = GetFile(file);
        // delete the file after conversion to bytes
        System.IO.File.Delete(file);
        // have the file download dialog only display the base name of the file            return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(file));

2
দয়া করে কখনও করবেন না, কখনও কখনও পুরো ফাইলগুলিকে মেমোরিতে প্রোডাকশনে লোড করুন
মাকদুমী
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.