वेब एपीआई का उपयोग करके किसी फ़ाइल को कैसे लौटाएं?


98

मैं ASP.NET वेब एपीआई का उपयोग कर रहा हूं ।
मैं एपीआई (कि एपीआई उत्पन्न करता है) से सी # के साथ एक पीडीएफ डाउनलोड करना चाहता हूं।

क्या मेरे पास एपीआई वापस आ सकता है byte[]? और C # एप्लिकेशन के लिए मैं बस कर सकता हूं:

byte[] pdf = client.DownloadData("urlToAPI");? 

तथा

File.WriteAllBytes()?

"वेब एपीआई"? वास्तव में आप का अर्थ क्या है? कृपया smallurl.com/so-hints को पढ़ें और अपने प्रश्न को संपादित करें।
जॉन स्कीट

1
@JonSkeet: ASP.NET के नवीनतम संस्करण में वेब एपीआई एक नई सुविधा है। देखें asp.net/whitepapers/mvc4-release-notes#_Toc317096197
रॉबर्ट हार्वे

1
@Robert: धन्यवाद - यह टैग स्पष्ट करता है, हालांकि "ASP.NET वेब एपीआई" का जिक्र अभी भी स्पष्ट होता। आंशिक रूप से एक सामान्य रूप से सामान्य नाम के लिए एमएस की गलती :)
जॉन स्कीट


कोई भी व्यक्ति जो वेब एपीआई और IHTTPActionResult के माध्यम से स्ट्रीम वापस करना चाहता है, तो यहां देखें: nodogmablog.bryanhogan.net/2017/02/…
IbrarMumtaz

जवाबों:


170

इसके अंदर स्ट्रीमकंटेंट के साथ HttpResponseMessage को वापस करना बेहतर है।

यहाँ उदाहरण है:

public HttpResponseMessage GetFile(string id)
{
    if (String.IsNullOrEmpty(id))
        return Request.CreateResponse(HttpStatusCode.BadRequest);

    string fileName;
    string localFilePath;
    int fileSize;

    localFilePath = getFileFromID(id, out fileName, out fileSize);

    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
    response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    response.Content.Headers.ContentDisposition.FileName = fileName;
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

    return response;
}

युपीडी द्वारा टिप्पणी से Patridge : चाहिए किसी और एक वास्तविक फ़ाइल के बजाय एक बाइट सरणी से एक प्रतिक्रिया से बाहर भेजने के लिए देख यहां मिलता है, आप StreamContent (देखें के बजाय नई ByteArrayContent (someData) का उपयोग करना चाहते करने जा रहे हैं यहाँ )।


1
पहली बात - जब आप एक ही फ़ाइल में इंगित दो FileStream ऑब्जेक्ट को नया कर रहे हैं, तो यह कोड एक अपवाद का कारण होगा। दूसरी बात यह है कि आप "उपयोग करना" कथन का उपयोग नहीं करना चाहते हैं, क्योंकि जैसे ही चर दायरे से बाहर हो जाता है, .NET इसे निपटाना होगा और आपको अंतर्निहित कनेक्शन बंद होने के बारे में त्रुटि संदेश मिलेगा।
ब्रैंडन मोंटगोमरी

48
क्या किसी और को यहां वास्तविक फ़ाइल के बजाय बाइट सरणी से प्रतिक्रिया भेजने की तलाश में है, तो आप new ByteArrayContent(someData)इसके बजाय StreamContent( यहां देखें ) का उपयोग करना चाहते हैं ।
पितृ पक्ष

आप बेस डिस्पोज () को ओवरराइड करना भी चाह सकते हैं ताकि फ्रेमवर्क के कॉल करने पर आप अपने संसाधनों को सही ढंग से संभाल सकें।
फिल कूपर

1
मैं यह बताना चाहूंगा कि सही MediaTypeHeaderValue महत्वपूर्ण है और इसे गतिशील बनाने के लिए यदि आपके पास अलग-अलग फ़ाइल प्रकार हैं, तो आप ऐसा कर सकते हैं। (जहाँ फ़ाइलनाम एक स्ट्रिंग है और इसमें एक फ़ाइल प्रकार होता है जैसे .jpg, .pdf, docx आदि ..) var contentType = MimeMapping.GetMimeMapping (fileName); response.Content.Headers.ContentType = new MediaTypeHeaderValue (contentType);
जिमीस्वाइन

1
क्या FileStream स्वतः ही निपट जाता है?
ब्रायन टैकर

37

मैंने निम्नलिखित कार्रवाई की:

[HttpGet]
[Route("api/DownloadPdfFile/{id}")]
public HttpResponseMessage DownloadPdfFile(long id)
{
    HttpResponseMessage result = null;
    try
    {
        SQL.File file = db.Files.Where(b => b.ID == id).SingleOrDefault();

        if (file == null)
        {
            result = Request.CreateResponse(HttpStatusCode.Gone);
        }
        else
        {
            // sendo file to client
            byte[] bytes = Convert.FromBase64String(file.pdfBase64);


            result = Request.CreateResponse(HttpStatusCode.OK);
            result.Content = new ByteArrayContent(bytes);
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            result.Content.Headers.ContentDisposition.FileName = file.name + ".pdf";
        }

        return result;
    }
    catch (Exception ex)
    {
        return Request.CreateResponse(HttpStatusCode.Gone);
    }
}

यह वास्तव में इस सवाल का जवाब देता है
मिक

1
यह बड़ी फ़ाइलों के साथ एक अच्छा विचार नहीं होगा क्योंकि यह पूरी छवि को मेमोरी में लोड करता है। स्ट्रीम का विकल्प बेहतर है।
पॉल रेडी

@PaulReedy बिल्कुल सही ... लेकिन बहुत सारे मामलों में, आपको बड़ी फ़ाइलों से निपटने की आवश्यकता नहीं है। लेकिन मैं आपकी बात से पूरी तरह सहमत हूँ!
एंड्रे डी मटोस फ़राज़

14

साथ उदाहरण IHttpActionResultमें ApiController

[HttpGet]
[Route("file/{id}/")]
public IHttpActionResult GetFileForCustomer(int id)
{
    if (id == 0)
      return BadRequest();

    var file = GetFile(id);

    IHttpActionResult response;
    HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.OK);
    responseMsg.Content = new ByteArrayContent(file.SomeData);
    responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName;
    responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    response = ResponseMessage(responseMsg);
    return response;
}

यदि आप पीडीएफ डाउनलोड नहीं करना चाहते हैं और निम्न दो लाइनों को हटाने के बजाय पीडीएफ दर्शक में निर्मित ब्राउज़रों का उपयोग करें:

responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName;

@ElbertJohnFelipe हां, आपको फ़ाइल मिलती है var file = GetFile(id);file.SomeDataएक बाइट ऐरे ( byte[]) है और file.FileNameहै string
ओगलास

आपके पोस्ट के लिए शुक्रिया। 'HttpResponseMessage' ने मेरे लिए ApiController के अंदर काम नहीं किया, इसलिए आपने मुझे बचा लिया।
मैक्स

13

बस एक नोट के लिए .Net Core: यदि हम कच्ची बाइट्स भेजना चाहते हैं, तो हम FileContentResultसामग्री का उपयोग कर सकते हैं और सेट कर सकते हैं application/octet-stream। उदाहरण:

[HttpGet("{id}")]
public IActionResult GetDocumentBytes(int id)
{
    byte[] byteArray = GetDocumentByteArray(id);
    return new FileContentResult(byteArray, "application/octet-stream");
}

1
यह महान काम करता है, इसके अलावा, अगर आप फ़ाइल नाम को नियंत्रित करना चाहते हैं कि वहाँ एक संपत्ति पर है FileContentResultकहा जाता है FileDownloadNameफ़ाइल नाम निर्दिष्ट करने के लिए
weeksdev

@weeksdev आह यह नहीं जानता था। टिप्पणी के लिए धन्यवाद।
अमीर शिराज़ी

यह धन्यवाद, धन्यवाद। सप्ताहदेव की टिप्पणी भी बहुत उपयोगी है।
13

1

मैं सोच रहा था कि क्या एक फ़ाइल को और अधिक ... "सामान्य" तरीके से डाउनलोड करने का एक सरल तरीका था। मैं यह लेकर आया।

यह एक सरल है ActionResultजो आपको एक नियंत्रक कॉल से एक फ़ाइल डाउनलोड करने की अनुमति देगा जो एक रिटर्न देता है IHttpActionResult। फ़ाइल में संग्रहीत है byte[] Content। जरूरत पड़ने पर आप इसे एक धारा में बदल सकते हैं।

मैंने इसका उपयोग डेटाबेस के वैरिएबल कॉलम में संग्रहीत फ़ाइलों को वापस करने के लिए किया।

    public class FileHttpActionResult : IHttpActionResult
    {
        public HttpRequestMessage Request { get; set; }

        public string FileName { get; set; }
        public string MediaType { get; set; }
        public HttpStatusCode StatusCode { get; set; }

        public byte[] Content { get; set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            HttpResponseMessage response = new HttpResponseMessage(StatusCode);

            response.StatusCode = StatusCode;
            response.Content = new StreamContent(new MemoryStream(Content));
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = FileName;
            response.Content.Headers.ContentType = new MediaTypeHeaderValue(MediaType);

            return Task.FromResult(response);
        }
    }

आपका कोड ओपी की समस्या को कैसे ठीक करता है, इसका संक्षिप्त विवरण आपके उत्तर की गुणवत्ता को बढ़ाएगा।
एड्रियन मोल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.