Uau, é muito mais simples fazer isso ao enviar arquivos grandes para a API REST. Não gosto de comentar obrigado, mas obrigado. É portátil para Windows Phone 8.
Léon Pelletier
1
Esse código falhou para mim, pois a cadeia de limite passada para new MultipartFormDataContent(...)continha um caractere de limite inválido (talvez o separador "/"). Sem erros, apenas nenhum arquivo publicado no servidor - no meu caso, Context.Request.Files.Count = 0 no controlador de API. Possivelmente apenas um Nancyproblema, mas sugiro usar algo parecido DateTime.Now.Ticks.ToString("x").
Se você receber um erro: " Arquivo (s) enviado (s) não encontrado (s) " tente adicionar o keyefileName parâmetros para content( bilddatei e upload.jpg neste exemplo).
Jhhwilliams # 24/19
1
@ KevinHarker, Releia esse segundo link. O parágrafo falando sobre não descartar o HttpClient estava se referindo ao design anterior. É fácil confundir. Basicamente, com o IHttpClientFactory, o HttpClient Dispose realmente não faz nada ( stackoverflow.com/a/54326424/476048 ) e os manipuladores internos são gerenciados pelo HttpClientFactory.
Berin Loritsch 15/07/19
83
Funciona mais ou menos assim (exemplo, usando um arquivo de imagem / jpg):
asyncpublicTask<HttpResponseMessage>UploadImage(string url,byte[]ImageData){var requestContent =newMultipartFormDataContent();// here you can specify boundary if you need---^var imageContent =newByteArrayContent(ImageData);
imageContent.Headers.ContentType=MediaTypeHeaderValue.Parse("image/jpeg");
requestContent.Add(imageContent,"image","image.jpg");returnawait client.PostAsync(url, requestContent);}
(Você pode requestContent.Add()o que quiser, dê uma olhada no descendente HttpContent para ver os tipos disponíveis a serem passados)
Quando concluído, você encontrará o conteúdo da resposta com HttpResponseMessage.Contento qual pode consumir HttpContent.ReadAs*Async.
Ahhh obrigado pela // here you can specify boundary if you need---^:)
sfarbota
1
por que isso não funciona? Tarefa assíncrona pública <string> SendImage (byte [] foto) {var requestContent = new MultipartFormDataContent (); var imageContent = novo ByteArrayContent (foto); imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse ("image / jpeg"); requestContent.Add (imageContent, "foto", "foto.jpg"); string url = " myAddress / myWS / api / Home / SendImage? foto = "; aguarde _client.PostAsync (url, requestContent); retornar "ok"; }
atapi19 29/01/19
1
asyncna primeira linha e awaitna linha antes da última são desnecessárias.
1valdis
Para arquivos grandes, adicione um conteúdo de fluxo à solicitação em vez de uma matriz de bytes.
Elisabeth
1
@WDRust, com uma matriz de bytes, você primeiro carrega o arquivo inteiro na memória e depois o envia. Com um conteúdo de fluxo, o arquivo é lido e enviado usando um buffer, que é mais eficiente em termos de memória.
Josef Bláha 27/05/19
53
Este é um exemplo de como postar string e fluxo de arquivos com HTTPClient usando MultipartFormDataContent. O Content-Disposition e o Content-Type precisam ser especificados para cada HTTPContent:
@ Trout Você não tem idéia de como seu código me fez tão feliz hoje! +1
Beliscar
6
Esta é a resposta completa.
VK
2
Eu sei que não devemos comentar uma nota de agradecimento. Mas esse aqui é o melhor código que eu já vi sobre como usar MultipartFormDataContent. Parabéns a você senhor
sebagomez 4/16
Acordado. Essa é a única resposta que inclui json string e file como parte do conteúdo da carga útil.
Frostshoxx
Eu testo no meu computador (win7 sp1, IIS 7.5) sem Content-Typee Content-Dispositionestá OK, mas no Server 2008 R2 (IIS 7.5) não consigo encontrar arquivos, é estranho. Então eu faço como resposta.
Chengzi 28/03/19
18
Aqui está outro exemplo de como usar o HttpClientupload de ummultipart/form-data .
Ele envia um arquivo para uma API REST e inclui o próprio arquivo (por exemplo, um JPG) e parâmetros adicionais da API. O arquivo é enviado diretamente do disco local via FileStream.
Veja aqui o exemplo completo, incluindo lógica específica da API adicional.
publicstaticasyncTaskUploadFileAsync(string token,string path,string channels){// we need to send a request with multipart/form-datavar multiForm =newMultipartFormDataContent();// add API method parameters
multiForm.Add(newStringContent(token),"token");
multiForm.Add(newStringContent(channels),"channels");// add file and directly upload itFileStream fs =File.OpenRead(path);
multiForm.Add(newStreamContent(fs),"file",Path.GetFileName(path));// send request to APIvar url ="https://slack.com/api/files.upload";var response =await client.PostAsync(url, multiForm);}
Sem falhas. Exatamente o que eu estava procurando em um TestServer.CreatClient()cenário do .NET Core de um teste de integração para um upload de dados + arquivo.
Vedran Mandić
se o método é HTTPGET como passar o formcontent
MBG
As solicitações GET do @MBG normalmente não têm um corpo de solicitação por convenção; portanto, você não pode fazer upload de um arquivo usando GET (ou não, a menos que o servidor para o qual você está enviando seja muito incomum - a maioria dos servidores da Web não espera ou o suporta) , porque não há um corpo de solicitação no qual incluir o arquivo ou os dados do formulário que o acompanham. Acredito que tecnicamente não há nada que impeça que isso seja feito na teoria; é apenas que a convenção em quase todas as implementações de HTTP é que, semanticamente, o GET é principalmente para recuperar informações (em vez de enviar) e, portanto, não tem um corpo
ADyson 17/07
9
Aqui está uma amostra completa que funcionou para mim. O boundaryvalor na solicitação é adicionado automaticamente pelo .NET.
@ Softlion - Estou tendo problemas para NÃO carregá-lo na memória antes de enviar. Se você conhece uma maneira melhor, poste aqui: stackoverflow.com/questions/52446969/…
emery.noel
1
Exemplo com o pré-carregador Dotnet 3.0 Core
ProgressMessageHandler processMessageHander =newProgressMessageHandler();
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 =newUri(transfer.BackEndUrl);
client.DefaultRequestHeaders.Authorization=newAuthenticationHeaderValue("Bearer",AccessToken);
using (MultipartFormDataContent multiForm =newMultipartFormDataContent()){
multiForm.Add(newStringContent(FileId),"FileId");
multiForm.Add(newStringContent(FileName),"FileName");string hash ="";
using (MD5 md5Hash = MD5.Create()){var sb =newStringBuilder();foreach(var data in md5Hash.ComputeHash(File.ReadAllBytes(FullName))){
sb.Append(data.ToString("x2"));}
hash = result.ToString();}
multiForm.Add(newStringContent(hash),"Hash");
using (FileStream fs =File.OpenRead(FullName)){
multiForm.Add(newStreamContent(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();}}}
Este cenário é uso para upload de arquivos no site da API com certificado de segurança
Rajenthiran T
0
Estou adicionando um trecho de código que mostra como postar um arquivo em uma API que foi exposta sobre o verbo http DELETE. Esse não é um caso comum para carregar um arquivo com o verbo http DELETE, mas é permitido. Eu assumi a autenticação Windows NTLM para autorizar a chamada.
O problema que se pode enfrentar é que todas as sobrecargas do HttpClient.DeleteAsyncmétodo não têm parâmetros para HttpContenta forma como o obtemos no PostAsyncmétodo
var requestUri =newUri("http://UrlOfTheApi");
using (var streamToPost =newMemoryStream("C:\temp.txt"))
using (var fileStreamContent =newStreamContent(streamToPost))
using (var httpClientHandler =newHttpClientHandler(){UseDefaultCredentials=true})
using (var httpClient =newHttpClient(httpClientHandler,true))
using (var requestMessage =newHttpRequestMessage(HttpMethod.Delete, requestUri))
using (var formDataContent =newMultipartFormDataContent()){
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();thrownewException("Error on the server : "+ erroResult);}}
Você precisa dos espaços para nome abaixo na parte superior do seu arquivo C #:
using System;
using System.Net;
using System.IO;
using System.Net.Http;
PS Desculpe por usar muitos blocos (padrão IDisposable) no meu código. Infelizmente, a sintaxe do uso da construção de C # não suporta a inicialização de várias variáveis na única instrução.
Você pode melhorar sua resposta comentando o código que escreveu
msrd0 11/11/19
OK msrd! Desculpe pelo meu novato. Eu tento colocar um código claro como "Erik Kalkoke", eu adoro isso. vou compartilhar meu código como receber imagem de IFormFile no nó 1 do servidor e passar para o nó 2 do servidor, aumentando algum texto via classe [MultipartFormDataContent] Oh! última linha como esta. resultado = aguardar res.Content.ReadAsStringAsync ();
Respostas:
meu resultado fica assim:
fonte
new MultipartFormDataContent(...)
continha um caractere de limite inválido (talvez o separador "/"). Sem erros, apenas nenhum arquivo publicado no servidor - no meu caso, Context.Request.Files.Count = 0 no controlador de API. Possivelmente apenas umNancy
problema, mas sugiro usar algo parecidoDateTime.Now.Ticks.ToString("x")
.key
efileName
parâmetros paracontent
( bilddatei e upload.jpg neste exemplo).Funciona mais ou menos assim (exemplo, usando um arquivo de imagem / jpg):
(Você pode
requestContent.Add()
o que quiser, dê uma olhada no descendente HttpContent para ver os tipos disponíveis a serem passados)Quando concluído, você encontrará o conteúdo da resposta com
HttpResponseMessage.Content
o qual pode consumirHttpContent.ReadAs*Async
.fonte
// here you can specify boundary if you need---^
:)async
na primeira linha eawait
na linha antes da última são desnecessárias.Este é um exemplo de como postar string e fluxo de arquivos com HTTPClient usando MultipartFormDataContent. O Content-Disposition e o Content-Type precisam ser especificados para cada HTTPContent:
Aqui está o meu exemplo. Espero que ajude:
fonte
MultipartFormDataContent
. Parabéns a você senhorContent-Type
eContent-Disposition
está OK, mas no Server 2008 R2 (IIS 7.5) não consigo encontrar arquivos, é estranho. Então eu faço como resposta.Aqui está outro exemplo de como usar o
HttpClient
upload de ummultipart/form-data
.Ele envia um arquivo para uma API REST e inclui o próprio arquivo (por exemplo, um JPG) e parâmetros adicionais da API. O arquivo é enviado diretamente do disco local via
FileStream
.Veja aqui o exemplo completo, incluindo lógica específica da API adicional.
fonte
Tente isso, está funcionando para mim.
fonte
TestServer.CreatClient()
cenário do .NET Core de um teste de integração para um upload de dados + arquivo.Aqui está uma amostra completa que funcionou para mim. O
boundary
valor na solicitação é adicionado automaticamente pelo .NET.fonte
Exemplo com o pré-carregador Dotnet 3.0 Core
fonte
fonte
Estou adicionando um trecho de código que mostra como postar um arquivo em uma API que foi exposta sobre o verbo http DELETE. Esse não é um caso comum para carregar um arquivo com o verbo http DELETE, mas é permitido. Eu assumi a autenticação Windows NTLM para autorizar a chamada.
O problema que se pode enfrentar é que todas as sobrecargas do
HttpClient.DeleteAsync
método não têm parâmetros paraHttpContent
a forma como o obtemos noPostAsync
métodoVocê precisa dos espaços para nome abaixo na parte superior do seu arquivo C #:
PS Desculpe por usar muitos blocos (padrão IDisposable) no meu código. Infelizmente, a sintaxe do uso da construção de C # não suporta a inicialização de várias variáveis na única instrução.
fonte
fonte