সি # এইচটিটিপি ক্লায়েন্ট 4.5 মাল্টিপার্ট / ফর্ম-ডেটা আপলোড


145

কেউ কীভাবে জানে। আপলোড HttpClientসহ নেট 4.5 ব্যবহার করতে হয় multipart/form-data?

আমি ইন্টারনেটে কোনও উদাহরণ খুঁজে পাইনি।


1
আমি চেষ্টা করেছিলাম তবে কীভাবে এটি শুরু করব তা সম্পর্কে আমার কোনও ধারণা নেই .. যেখানে আমি সামগ্রীতে বাইটআরারি যুক্ত করব এবং আরও কিছু। আমার একটি প্রারম্ভিক সহায়তা দরকার।
ident

আপনি এই পোস্টের উত্তর দেখতে পারেন। (প্রক্সি সেটিংস সহ) স্ট্যাকওভারফ্লো.
com

উত্তর:


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
বাহ, REST এপিআইতে বড় ফাইলগুলি আপলোড করার সময় এটি করা এত সহজ। আমি ধন্যবাদ জানাতে চাই না, তবে ধন্যবাদ। এটি উইন্ডোজ ফোন ৮ এর জন্য বহনযোগ্য
লোন পেলেটিয়ার

1
এই কোডটি আমার পক্ষে ব্যর্থ হয়েছিল কারণ সীমানা স্ট্রিংটিতে new MultipartFormDataContent(...)একটি অবৈধ সীমানা চরিত্র (সম্ভবত "/" বিভাজক) রয়েছে। কোনও ত্রুটি নেই, সার্ভারে কেবল কোনও ফাইল পোস্ট করা হয়নি - আমার ক্ষেত্রে, Context.Request.Files.Count = 0 এপিআই নিয়ন্ত্রণকারীতে। সম্ভবত কেবল একটি Nancyসমস্যা, তবে আমি DateTime.Now.Ticks.ToString("x")পরিবর্তে এর মতো কিছু ব্যবহার করার পরামর্শ দিচ্ছি ।
ডানক

7
@ মরিসিসিও অ্যাভিলস, আপনার লিঙ্কটি নষ্ট হয়েছে। আমি এটি একটি পেয়েছি যা এটি সুন্দরভাবে ব্যাখ্যা করেছে: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
কেভিন হার্কার

1
যদি আপনি একটি ত্রুটি পান: " আপলোড করা ফাইল (গুলি) পাওয়া যায় নি " keyএবং এই fileNameপরামিতিগুলিকে content( উদাহরণস্বরূপ বিল্ডডেটি এবং আপলোড.জেপজি ) যুক্ত করার চেষ্টা করুন ।
jhhwilliams

1
কেভিনহার্কার, দ্বিতীয় লিঙ্কটি আবার পড়ুন। এইচটিপিপ্লেইয়েন্টকে নিষ্পত্তি না করার বিষয়ে কথা বলার অনুচ্ছেদটি পূর্ববর্তী নকশাকে বোঝাচ্ছিল। এটা বিভ্রান্ত করা সহজ। মূলত, IHttpClientFactory সঙ্গে HttpClient নিষ্পত্তি সত্যিই কিছু (করে না stackoverflow.com/a/54326424/476048 ) এবং অভ্যন্তরীণ হ্যান্ডেলার HttpClientFactory দ্বারা পরিচালিত হয়।
বেরিন লরিটস্ক

83

এটি কমবেশি এর মতো কাজ করে (উদাহরণস্বরূপ কোনও চিত্র / জেপিজি ফাইল ব্যবহার করে):

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()যা খুশি তাই করতে পারেন, এইচটিটিপি কনটেন্ট বংশধরকে একবার দেখুন করার জন্য উপলব্ধ প্রকারগুলি দেখতে )

সম্পূর্ণ হয়ে গেলে, আপনি HttpResponseMessage.Contentভোজন করতে পারেন এমন প্রতিক্রিয়া সামগ্রীটি ভিতরে খুঁজে পাবেন HttpContent.ReadAs*Async


2
// here you can specify boundary if you need---^
আহঃ

1
কেন এটি কাজ করে না? পাবলিক অ্যাসিঙ্ক টাস্ক <স্ট্রিং> সেন্ড ইমেজ (বাইট [] ফোটো) {var অনুরোধকন্ট = নতুন মাল্টিপার্টফর্মডেটা কনটেন্ট (); var ইমেজ কনটেন্ট = নতুন বাইটআরারি কনটেন্ট (ফোটো); ইমেজকন্টেন্ট.হেইডার্স.কন্টেন্টটাইপ = মিডিয়াটাইপহাইডারভ্যালু.পার্স ("চিত্র / জেপিগ"); অনুরোধকন্টেন্ট.এড (চিত্রকন্টেন্ট, "ফটো", "foto.jpg"); স্ট্রিং url = " মাইএড্রেস / মাইডাব্লুএস / এপি / হোম / সেন্ড ইমেজ? ফটো = "; অপেক্ষা করুন _প্রেম.পোস্টএন্সিঙ্ক (ইউআরএল, রিকোয়েস্টকন্টেন্ট); "ঠিক আছে" ফিরে; }
atapi19

1
asyncপ্রথম লাইনে এবং awaitলাইনের আগে শেষের আগে অপ্রয়োজনীয়।
1valdis

বড় ফাইলগুলির জন্য, বাইট অ্যারের পরিবর্তে অনুরোধে একটি স্ট্রিম সামগ্রী যুক্ত করুন।
এলিজাবেথ

1
@WDRust, বাইট অ্যারে সহ, আপনি প্রথমে পুরো ফাইলটি মেমোরিতে লোড করুন এবং তারপরে এটি প্রেরণ করুন। একটি স্ট্রিম সামগ্রী সহ, ফাইলটি বাফার ব্যবহার করে পড়া এবং প্রেরণ করা হয়, যা মেমরির ক্ষেত্রে আরও দক্ষ।
জোসেফ ব্লাহা

53

মাল্টিপার্টফর্মডাটা কনটেন্ট ব্যবহার করে এইচটিটিপিপ্লায়েন্টের সাথে স্ট্রিং এবং ফাইল স্ট্রিম পোস্ট করার জন্য এটি উদাহরণ। প্রতিটি HTTP কনটেন্টের জন্য সামগ্রী-বিশৃঙ্খলা এবং বিষয়বস্তুর ধরণ নির্দিষ্ট করা দরকার:

এখানে আমার উদাহরণ। আশা করি এটা সাহায্য করবে:

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 স্ট্রিং এবং ফাইল অন্তর্ভুক্ত।
frostshoxx

আমি আমার কম্পিউটারে (উইন 7 এসপি 1, আইআইএস 7.5) পরীক্ষা করেছি Content-Typeএবং Content-Dispositionঠিক আছে, তবে সার্ভার ২০০৮ আর 2 (আইআইএস 7.5) এ ফাইলগুলি খুঁজে পাওয়া যায় না, এটি আশ্চর্যের বিষয়। সুতরাং আমি উত্তর হিসাবে না।
চেঞ্জি

18

কীভাবে HttpClientআপলোড করতে হয় তার আরেকটি উদাহরণ এখানে multipart/form-data

এটি একটি ফাইলকে একটি আরএসটি এপিআইতে আপলোড করে এবং ফাইলটি নিজেই (যেমন একটি জেপিজি) এবং অতিরিক্ত এপিআই প্যারামিটার অন্তর্ভুক্ত করে। ফাইলটি স্থানীয় ডিস্ক থেকে সরাসরি আপলোড করা হয় FileStream

অতিরিক্ত এপিআই নির্দিষ্ট যুক্তি সহ পুরো উদাহরণের জন্য এখানে দেখুন ।

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 হয় কীভাবে ফর্ম কনটেন্টটি পাস করবেন
এমবিজি

@ এমবিজি জিইটি অনুরোধগুলির সাধারণত কনভেনশন দ্বারা একটি অনুরোধের বডি থাকে না, সুতরাং আপনি জিইটি ব্যবহার করে কোনও ফাইল আপলোড করতে পারবেন না (বা আপনি যে সার্ভারটি পাঠাচ্ছেন এটি খুব অস্বাভাবিক না হলে - বেশিরভাগ ওয়েবসার্স এটি আশা করে না বা সমর্থন করে না) , কারণ ফাইল বা তার সাথে ফর্ম ডেটা অন্তর্ভুক্ত করার জন্য কোনও অনুরোধ সংস্থা নেই। আমি বিশ্বাস করি যে প্রযুক্তিগতভাবে এটি তাত্ত্বিকভাবে করা থেকে বিরত হতে পারে এমন কিছুই নেই, এইচটিটিপি-র প্রায় সমস্ত বাস্তবায়ন জুড়েই এই কনভেনশনটি শব্দার্থকভাবে বলা হয় যে, জিইটি মূলত তথ্য আহরণের জন্য (প্রেরণের চেয়ে) এবং তাই এর কোনও দেহ নেই
এডিসন

9

আমার জন্য কাজ করে এমন একটি সম্পূর্ণ নমুনা এখানে। boundaryঅনুরোধে মান .NET দ্বারা স্বয়ংক্রিয়ভাবে যোগ করা হয়।

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/...

@ সফট্লিয়ন - প্রেরণের আগে এটিকে মেমরিতে লোড করতে আমার সমস্যা হচ্ছে। : আপনি একটি ভাল উপায় জানা থাকে, এখানে পোস্ট করুন stackoverflow.com/questions/52446969/...
emery.noel

1

প্রিলোডার ডটনেট 3.0 কোর সহ উদাহরণ with

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

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

সমস্যা এক শক্তি মুখ যে সব overloads যে 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);
    }
}

আপনার সি # ফাইলের শীর্ষে আপনার নেমস্পেসের নীচে প্রয়োজন:

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

আপনি যে কোডটি লিখেছেন তাতে মন্তব্য করে নিজের উত্তরটি উন্নত করতে পারেন
এমএসআরড0

ঠিক আছে এমএসআরড! আমার নবজাতক সম্পর্কে দুঃখিত। আমি "এরিক কালকোকে" এর মতো একটি পরিষ্কার কোড দেওয়ার চেষ্টা করি, আমি এটি পছন্দ করি। IFormFile দ্বারা সার্ভার নোড 1 এ চিত্র গ্রহণ এবং ক্লাসের মাধ্যমে কিছু পাঠ্য বাড়িয়ে সার্ভার নোড 2 এ পাস করার মতো আমার কোডটি ভাগ করব [মাল্টিপার্টফর্মডাটা কনটেন্ট] ওহ! এই মত শেষ লাইন। ফলাফল = অপেক্ষা করুন res.Content.ReadAsStringAsync ();
জ্যাক দ্য রিপার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.