C # HttpClient 4.5 मल्टीपार्ट / फॉर्म-डेटा अपलोड


145

क्या किसी को पता है कि HttpClient.net 4.5 का उपयोग किस तरह से किया जाता हैmultipart/form-data अपलोड के ?

मुझे इंटरनेट पर कोई उदाहरण नहीं मिला।


1
मैं कोशिश करूँगा, लेकिन मुझे यह पता नहीं है कि इसे कैसे शुरू किया जाए .. जहाँ मैं सामग्री और इतने पर बाइट को जोड़ दूं। मुझे एक तरह की शुरुआत की मदद चाहिए।
पहचान

आप इस पोस्ट का जवाब देख सकते हैं। (प्रॉक्सी सेटिंग के साथ) stackoverflow.com/a/50462636/2123797
Ergin ikelik

जवाबों:


156

मेरा परिणाम इस तरह दिखता है:

public static async Task<string> Upload(byte[] image)
{
     using (var client = new HttpClient())
     {
         using (var content =
             new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
         {
             content.Add(new StreamContent(new MemoryStream(image)), "bilddatei", "upload.jpg");

              using (
                 var message =
                     await client.PostAsync("http://www.directupload.net/index.php?mode=upload", content))
              {
                  var input = await message.Content.ReadAsStringAsync();

                  return !string.IsNullOrWhiteSpace(input) ? Regex.Match(input, @"http://\w*\.directupload\.net/images/\d*/\w*\.[a-z]{3}").Value : null;
              }
          }
     }
}

6
WEST, REST API में बड़ी फ़ाइलों को अपलोड करते समय ऐसा करना बहुत सरल है। मुझे धन्यवाद के लिए टिप्पणी करना पसंद नहीं है, लेकिन धन्यवाद। यह विंडोज फोन 8 के लिए पोर्टेबल है
लियोन पेलेटियर

1
यह कोड मेरे लिए विफल रहा क्योंकि सीमा स्ट्रिंग new MultipartFormDataContent(...)में एक अमान्य सीमा वर्ण (शायद "/" विभाजक) शामिल था। कोई त्रुटि नहीं, बस सर्वर में कोई फ़ाइल पोस्ट नहीं की गई - मेरे मामले में, Context.Request.Files.Count = 0 एपीआई नियंत्रक में। संभवतः सिर्फ एक Nancyमुद्दा है, लेकिन मैं DateTime.Now.Ticks.ToString("x")इसके बजाय कुछ का उपयोग करने का सुझाव देता हूं ।
डनक

7
@MauricioAviles, आपका लिंक टूट गया है। मुझे यह एक ऐसा मिला, जिसने इसे अच्छी तरह समझाया: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
केविन

1
यदि आपको कोई त्रुटि मिलती है: " अपलोड की गई फ़ाइल (एस) नहीं मिली है " keyऔर ( इस उदाहरण में bilddatei और upload.jpg ) के fileNameमापदंडों को जोड़ने की कोशिश करें । content
jhhwilliams

1
@KevinHarker, उस दूसरी कड़ी को फिर से पढ़ना। HttpClient को निपटाने के बारे में बात करने वाला पैराग्राफ पिछले डिज़ाइन का जिक्र कर रहा था। इसे भ्रमित करना आसान है। मूल रूप से, IHttpClientFactory के साथ, HttpClient डिस्पोज़ वास्तव में कुछ भी नहीं करता है ( stackoverflow.com/a/54326424/476048 ) और आंतरिक हैंडलर को HttpClientfactory द्वारा प्रबंधित किया जाता है।
बेरिन लोरिट्श

83

यह कमोबेश इसी तरह काम करता है (उदाहरण / इमेज / jpg फाइल का उपयोग करके):

async public Task<HttpResponseMessage> UploadImage(string url, byte[] ImageData)
{
    var requestContent = new MultipartFormDataContent(); 
    //    here you can specify boundary if you need---^
    var imageContent = new ByteArrayContent(ImageData);
    imageContent.Headers.ContentType = 
        MediaTypeHeaderValue.Parse("image/jpeg");

    requestContent.Add(imageContent, "image", "image.jpg");

    return await client.PostAsync(url, requestContent);
}

(आप requestContent.Add()जो चाहें कर सकते हैं, HttpContent वंशज पर एक नज़र डालें ताकि पास होने के लिए उपलब्ध प्रकार देखें)

जब पूरा हो जाए, तो आपको अंदर HttpResponseMessage.Contentऐसी प्रतिक्रिया सामग्री मिल जाएगी जिसका आप उपभोग कर सकते हैं HttpContent.ReadAs*Async


2
आह के लिए धन्यवाद // here you can specify boundary if you need---^:)
sfarbota

1
यह काम क्यों नहीं करता है? सार्वजनिक async टास्क <string> SendImage (बाइट [] फोटो) {var requestContent = new MultipartFormDataContent (); var imageContent = new ByteArrayContent (foto); imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse ("image / jpeg"); requestContent.Add (imageContent, "foto", "foto.jpg"); string url = " myAddress / myWS / api / Home / SendImage? foto = "; इंतजार _client.PostAsync (url, requestContent); वापसी "ठीक है"; }
atapi19

1
asyncपहली लाइन awaitपर और आखिरी से पहले लाइन पर अनावश्यक हैं।
अवधी 23

बड़ी फ़ाइलों के लिए, एक बाइट सरणी के बजाय अनुरोध पर एक स्ट्रीम सामग्री जोड़ें।
एलिजाबेथ

1
@DRust, एक बाइट सरणी के साथ, आप पहले पूरी फ़ाइल को मेमोरी में लोड करते हैं और फिर इसे भेजते हैं। स्ट्रीम कंटेंट के साथ, फ़ाइल को बफर का उपयोग करके पढ़ा और भेजा जाता है, जो मेमोरी के मामले में अधिक कुशल है।
जोसेफ ब्लाहा

53

यह कैसे MultipartFormDataContent का उपयोग करके HTTPClient के साथ स्ट्रिंग और फ़ाइल स्ट्रीम पोस्ट करने का एक उदाहरण है। प्रत्येक HTTPContent के लिए सामग्री-विवाद और सामग्री-प्रकार निर्दिष्ट करने की आवश्यकता है:

यहाँ मेरा उदाहरण है। आशा करता हूँ की ये काम करेगा:

private static void Upload()
{
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("User-Agent", "CBS Brightcove API Service");

        using (var content = new MultipartFormDataContent())
        {
            var path = @"C:\B2BAssetRoot\files\596086\596086.1.mp4";

            string assetName = Path.GetFileName(path);

            var request = new HTTPBrightCoveRequest()
                {
                    Method = "create_video",
                    Parameters = new Params()
                        {
                            CreateMultipleRenditions = "true",
                            EncodeTo = EncodeTo.Mp4.ToString().ToUpper(),
                            Token = "x8sLalfXacgn-4CzhTBm7uaCxVAPjvKqTf1oXpwLVYYoCkejZUsYtg..",
                            Video = new Video()
                                {
                                    Name = assetName,
                                    ReferenceId = Guid.NewGuid().ToString(),
                                    ShortDescription = assetName
                                }
                        }
                };

            //Content-Disposition: form-data; name="json"
            var stringContent = new StringContent(JsonConvert.SerializeObject(request));
            stringContent.Headers.Add("Content-Disposition", "form-data; name=\"json\"");
            content.Add(stringContent, "json");

            FileStream fs = File.OpenRead(path);

            var streamContent = new StreamContent(fs);
            streamContent.Headers.Add("Content-Type", "application/octet-stream");
            //Content-Disposition: form-data; name="file"; filename="C:\B2BAssetRoot\files\596090\596090.1.mp4";
            streamContent.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + Path.GetFileName(path) + "\"");
            content.Add(streamContent, "file", Path.GetFileName(path));

            //content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

            Task<HttpResponseMessage> message = client.PostAsync("http://api.brightcove.com/services/post", content);

            var input = message.Result.Content.ReadAsStringAsync();
            Console.WriteLine(input.Result);
            Console.Read();
        }
    }
}

11
@ के बारे में आपको पता नहीं है कि आज आपके कोड ने मुझे कितना खुश कर दिया है! +1
चुटकी

6
यह पूरा जवाब है।
वीके

2
मुझे पता है कि हम आपको धन्यवाद नोट टिप्पणी करने वाले नहीं हैं। लेकिन यह यहीं सबसे अच्छा कोड है जिसका मैंने उपयोग करने के तरीके पर देखा है MultipartFormDataContent
यंग यू टू

माना। यह एकमात्र उत्तर है जिसमें पेलोड सामग्री के भाग के रूप में json string और फ़ाइल शामिल है।
फ्रॉस्टशोक्स

मैं अपने कंप्यूटर पर परीक्षण करता हूं (बिना win7 sp1, IIS 7.5) Content-Typeऔर Content-Dispositionठीक है, लेकिन सर्वर 2008 R2 (IIS 7.5) पर फाइलें नहीं मिल सकती हैं, यह अजीब है। तो मैं जवाब के रूप में करता हूं।
चेंग्जी

18

यहाँ एक और उदाहरण है कि कैसे HttpClientअपलोड करने के लिए उपयोग करेंmultipart/form-data

यह एक फ़ाइल को REST API में अपलोड करता है और इसमें फ़ाइल (जैसे JPG) और अतिरिक्त API पैरामीटर शामिल हैं। फ़ाइल को स्थानीय डिस्क से सीधे अपलोड किया जाता हैFileStream

अतिरिक्त API विशिष्ट तर्क सहित पूर्ण उदाहरण के लिए यहां देखें ।

public static async Task UploadFileAsync(string token, string path, string channels)
{
    // we need to send a request with multipart/form-data
    var multiForm = new MultipartFormDataContent();

    // add API method parameters
    multiForm.Add(new StringContent(token), "token");
    multiForm.Add(new StringContent(channels), "channels");

    // add file and directly upload it
    FileStream fs = File.OpenRead(path);
    multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(path));

    // send request to API
    var url = "https://slack.com/api/files.upload";
    var response = await client.PostAsync(url, multiForm);
}

12

मेरे लिए इसके काम करने की कोशिश करो।

private static async Task<object> Upload(string actionUrl)
{
    Image newImage = Image.FromFile(@"Absolute Path of image");
    ImageConverter _imageConverter = new ImageConverter();
    byte[] paramFileStream= (byte[])_imageConverter.ConvertTo(newImage, typeof(byte[]));

    var formContent = new MultipartFormDataContent
    {
        // Send form text values here
        {new StringContent("value1"),"key1"},
        {new StringContent("value2"),"key2" },
        // Send Image Here
        {new StreamContent(new MemoryStream(paramFileStream)),"imagekey","filename.jpg"}
    };

    var myHttpClient = new HttpClient();
    var response = await myHttpClient.PostAsync(actionUrl.ToString(), formContent);
    string stringContent = await response.Content.ReadAsStringAsync();

    return response;
}

निर्दोष। वास्तव में मैं TestServer.CreatClient()जो डेटा + फ़ाइल अपलोड के लिए एकीकरण परीक्षण के .NET कोर परिदृश्य में देख रहा था ।
वेदरन मांडिक

यदि विधि HTTPGET है तो फॉर्मकंटेंट कैसे पास किया जाए
MBG

@MBG GET अनुरोधों में आम तौर पर कन्वेंशन द्वारा एक अनुरोध निकाय नहीं होता है, इसलिए आप GET का उपयोग करके एक फ़ाइल अपलोड नहीं कर सकते (या जब तक कि आपके द्वारा भेजा जा रहा सर्वर बहुत असामान्य न हो - अधिकांश वेबसर्वर इसकी उम्मीद नहीं करेंगे या इसका समर्थन नहीं करेंगे) , क्योंकि इसमें कोई अनुरोध निकाय नहीं है जिसमें फ़ाइल या साथ में फ़ॉर्म डेटा शामिल करना है। मेरा मानना ​​है कि तकनीकी रूप से ऐसा कुछ भी नहीं है जो इसे सिद्धांत रूप में करने से रोकेगा, यह सिर्फ इतना है कि HTTP के लगभग सभी कार्यान्वयनों में कन्वेंशन यह है कि शब्दार्थ, जीईटी मुख्य रूप से सूचना प्राप्त करने के लिए है (भेजने के बजाय) और इसलिए इसमें शरीर नहीं है
एडीसन

9

यहां एक पूर्ण नमूना है जो मेरे लिए काम करता है। boundaryअनुरोध में मूल्य नेट द्वारा स्वचालित रूप से जोड़ा जाता है।

var url = "http://localhost/api/v1/yourendpointhere";
var filePath = @"C:\path\to\image.jpg";

HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();

FileStream fs = File.OpenRead(filePath);
var streamContent = new StreamContent(fs);

var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

form.Add(imageContent, "image", Path.GetFileName(filePath));
var response = httpClient.PostAsync(url, form).Result;

हम इसके साथ टोकन कैसे भेज सकते हैं? कृपया इसे देखें: stackoverflow.com/questions/48295877/…

@Softlion - मुझे भेजने से पहले इसे मेमोरी में लोड करने में परेशानी नहीं हो रही है। यदि आप एक बेहतर तरीका जानते हैं, तो कृपया यहाँ पोस्ट करें: stackoverflow.com/questions/52446969/…
emery.noel

1

प्रीलोडर डॉटनेट 3.0 कोर के साथ उदाहरण

ProgressMessageHandler processMessageHander = new ProgressMessageHandler();

processMessageHander.HttpSendProgress += (s, e) =>
{
    if (e.ProgressPercentage > 0)
    {
        ProgressPercentage = e.ProgressPercentage;
        TotalBytes = e.TotalBytes;
        progressAction?.Invoke(progressFile);
    }
};

using (var client = HttpClientFactory.Create(processMessageHander))
{
    var uri = new Uri(transfer.BackEndUrl);
    client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", AccessToken);

    using (MultipartFormDataContent multiForm = new MultipartFormDataContent())
    {
        multiForm.Add(new StringContent(FileId), "FileId");
        multiForm.Add(new StringContent(FileName), "FileName");
        string hash = "";

        using (MD5 md5Hash = MD5.Create())
        {
            var sb = new StringBuilder();
            foreach (var data in md5Hash.ComputeHash(File.ReadAllBytes(FullName)))
            {
                sb.Append(data.ToString("x2"));
            }
            hash = result.ToString();
        }
        multiForm.Add(new StringContent(hash), "Hash");

        using (FileStream fs = File.OpenRead(FullName))
        {
            multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(FullName));
            var response = await client.PostAsync(uri, multiForm);
            progressFile.Message = response.ToString();

            if (response.IsSuccessStatusCode) {
                progressAction?.Invoke(progressFile);
            } else {
                progressErrorAction?.Invoke(progressFile);
            }
            response.EnsureSuccessStatusCode();
        }
    }
}

1
X509Certificate clientKey1 = null;
clientKey1 = new X509Certificate(AppSetting["certificatePath"],
AppSetting["pswd"]);
string url = "https://EndPointAddress";
FileStream fs = File.OpenRead(FilePath);
var streamContent = new StreamContent(fs);

var FileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
FileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("ContentType");
var handler = new WebRequestHandler();


handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(clientKey1);
handler.ServerCertificateValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) =>
{
    return true;
};


using (var client = new HttpClient(handler))
{
    // Post it
    HttpResponseMessage httpResponseMessage = client.PostAsync(url, FileContent).Result;

    if (!httpResponseMessage.IsSuccessStatusCode)
    {
        string ss = httpResponseMessage.StatusCode.ToString();
    }
}

यह परिदृश्य सुरक्षा प्रमाणपत्र के साथ एपीआई साइट में फ़ाइल अपलोड के लिए उपयोग किया जाता है
राजथिरन टी

0

मैं एक कोड स्निपेट जोड़ रहा हूं, जो यह दर्शाता है कि एक फ़ाइल को एपीआई पर कैसे पोस्ट किया जाए जो DELETE http क्रिया पर उजागर हो। यह DELETE http क्रिया के साथ फ़ाइल अपलोड करने के लिए एक सामान्य मामला नहीं है, लेकिन इसकी अनुमति है। मैंने कॉल को अधिकृत करने के लिए Windows NTLM प्रमाणीकरण मान लिया है।

समस्या जो एक का सामना कर सकती है वह यह है कि HttpClient.DeleteAsyncविधि के सभी अधिभार के पास HttpContentउस तरीके के लिए कोई पैरामीटर नहीं है जो हम इसे PostAsyncविधि में प्राप्त करते हैं

var requestUri = new Uri("http://UrlOfTheApi");
using (var streamToPost = new MemoryStream("C:\temp.txt"))
using (var fileStreamContent = new StreamContent(streamToPost))
using (var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true })
using (var httpClient = new HttpClient(httpClientHandler, true))
using (var requestMessage = new HttpRequestMessage(HttpMethod.Delete, requestUri))
using (var formDataContent = new MultipartFormDataContent())
{
    formDataContent.Add(fileStreamContent, "myFile", "temp.txt");
    requestMessage.Content = formDataContent;
    var response = httpClient.SendAsync(requestMessage).GetAwaiter().GetResult();

    if (response.IsSuccessStatusCode)
    {
        // File upload was successfull
    }
    else
    {
        var erroResult = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        throw new Exception("Error on the server : " + erroResult);
    }
}

आपको अपनी C # फ़ाइल के शीर्ष पर नीचे नामस्थान चाहिए:

using System;
using System.Net;
using System.IO;
using System.Net.Http;

पुनश्च मेरे कोड में ब्लॉक (आईडीसॉर्पोरेटरी पैटर्न) का उपयोग करने के बारे में क्षमा करें। दुर्भाग्य से, सी # के निर्माण का उपयोग करने का वाक्य-विन्यास एकल विवरण में कई चर को शुरू करने का समर्थन नहीं करता है।


-3
public async Task<object> PassImageWithText(IFormFile files)
{
    byte[] data;
    string result = "";
    ByteArrayContent bytes;

    MultipartFormDataContent multiForm = new MultipartFormDataContent();

    try
    {
        using (var client = new HttpClient())
        {
            using (var br = new BinaryReader(files.OpenReadStream()))
            {
                data = br.ReadBytes((int)files.OpenReadStream().Length);
            }

            bytes = new ByteArrayContent(data);
            multiForm.Add(bytes, "files", files.FileName);
            multiForm.Add(new StringContent("value1"), "key1");
            multiForm.Add(new StringContent("value2"), "key2");

            var res = await client.PostAsync(_MEDIA_ADD_IMG_URL, multiForm);
        }
    }
    catch (Exception e)
    {
        throw new Exception(e.ToString());
    }

    return result;
}

आपके द्वारा लिखे गए कोड पर टिप्पणी करके आप अपना उत्तर सुधार सकते हैं
msrd0

ठीक है msrd! मेरे नौसिखिये के बारे में क्षमा करें। मैं "एरिक कालकोक" जैसे स्पष्ट कोड डालने की कोशिश करता हूं, मुझे यह पसंद है। मैं सर्वर नोड 1 पर IFormFile द्वारा प्राप्त छवि की तरह अपना कोड साझा करूँगा और कक्षा [MultipartFormDataContent] के माध्यम से कुछ पाठ बढ़ाकर सर्वर नोड 2 पास करूँगा! इस तरह अंतिम पंक्ति। परिणाम = प्रतीक्षारत res.Content.ReadAsStringAsync ();
जैक द रिपर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.