I'm trying to upload files via web api, the files are sent as byte[].
I manage to upload only one file per request, but if I select multiple files it only upload one file.
This is the client side code:
var content = new MultipartFormDataContent();
ByteArrayContent byteContent = new ByteArrayContent(_mediaFile);
content.Add(byteContent, "file", _mediaFIleName);
var httpClient = new HttpClient();
var uploadServiceBaseAddress = "http://localhost:1000/api/home/Upload";
var httpResponseMessage = httpClient.PostAsync(uploadServiceBaseAddress, content);
This is the server side code:
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/uploads" + postedFile.FileName);
postedFile.SaveAs(filePath);
}
Is there another method to do this or am I doing something wrong here in the code above?
see this example
[HttpGet]
public IHttpActionResult SendBytes(string input)
{
string[] paths = input.Split('*');
foreach (var path in paths)
{
var content = new MultipartFormDataContent();
ByteArrayContent byteContent = new ByteArrayContent(File.ReadAllBytes(path));
content.Add(byteContent, "file", path);
var httpClient = new HttpClient();
var uploadServiceBaseAddress = "http://localhost:56381/api/BazarAlborzApp/RecieveBytes";
var httpResponseMessage = httpClient.PostAsync(uploadServiceBaseAddress, content);
}
return Ok<int>(0);
}
[HttpPost]
public IHttpActionResult RecieveBytes()
{
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = Path.Combine(HttpContext.Current.Server.MapPath("/uploads/" + postedFile.FileName));
postedFile.SaveAs(filePath);
}
return Ok<int>(0);
}
Related
Trying to make a post request from one application to another using the same Form Data parameters that the first one received.
both application controller currently have same method:
public async Task<ActionResult> TestSet()
{
var inputString = Request.Form["inputString"];
var inputFile = Request.Files[0];
var resultString = await _service.Set(inputString, inputFile.FileName, inputFile.ContentType, inputFile.InputStream);
return new MyJsonResult(new
{
fileName = resultString
});
}
which return json string:
{"fileName": "someFileName.png"}
Trying to make the first method to be something like this
public async Task<ActionResult> TestSet()
{
var inputString = Request.Form["inputString"];
var inputFile = Request.Files[0];
if (!string.IsNullOrEmpty(_redirectUrl))
{
using (var client = new HttpClient())
{
HttpContent content = GetContentSomehow(this.Request); // this i have an issue with
var response = await client.PostAsync(_redirectUrl, content);
var responseString = await response.Content.ReadAsStringAsync();
return new MyJsonResult(responseString);
}
}
var resultString = await _service.Set(inputString, inputFile.FileName, inputFile.ContentType, inputFile.InputStream);
return new MyJsonResult(new
{
fileName = resultString
});
}
This could help to get ByteArrayContent for File only.
And this would probably work to get the non-file parameters into StringContent, but how to get both of them into single Content?
var jsonString = JsonConvert.SerializeObject(Request.Form.ToDictionary());
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
Solved this issue by cominig StringContent and StreamContent into MultipartFormDataContent
public static MultipartFormDataContent GetMultipartFormData(HttpRequestBase req)
{
var formData = new MultipartFormDataContent();
//formData.Headers.ContentType.MediaType = "multipart/form-data";
foreach (var row in req.Form.ToDictionary())
{
formData.Add(new StringContent(row.Value), row.Key);
}
var file = req.Files[0];
StreamContent fileStreamContent = new StreamContent(file.InputStream);
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
formData.Add(fileStreamContent, file.FileName, file.FileName);
return formData;
}
I am looking to upload a file with some associated data from a C# win app to a WebAPI 2.0 using HTTP POST, but the request does not seems to be created corectly, however when I try to send them seperately it works fine.
Below is Win App Code for Upload:
public bool Upload(string url, string filePath, string localFilename, string uploadFileName)
{
Boolean isFileUploaded = false;
HttpClient httpClient = new HttpClient();
var fileStream = File.Open(localFilename, FileMode.Open);
var fileInfo = new FileInfo(localFilename);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Headers.Add("filePath", filePath);
content.Add(new StreamContent(fileStream), "\"file\"", string.Format("\"{0}\"", uploadFileName + fileInfo.Extension));
TestDocument td = new TestDocument();
td.Field1 = "ABC";
td.Field2 = "PQR";
string json = JsonConvert.SerializeObject(td);
var httpContent = new StringContent(json, Encoding.UTF8, "multipart/form-data");
content.Add(httpContent);
var result = httpClient.PostAsync(url, content);
return true;
}
At Api end:
[HttpPost]
public HttpResponseMessage Post([FromBody] Testdocument document)
{
HttpResponseMessage result = null;
Testdocument otd = new Testdocument();
otd = document;
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/App_Data/" + postedFile.FileName);
postedFile.SaveAs(filePath);
docfiles.Add(filePath);
}
result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}
Any suggestions on this?
I am trying to write code to upload file(s) by WinForm app to WebApi.
The WebApi code is like:
[HttpPost]
[Route("UploadEnvelope")]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
public Task<HttpResponseMessage> PostUploadEnvelope()
{
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/uploads");
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).ContinueWith<HttpResponseMessage>(o =>
{
foreach (MultipartFileData fileData in provider.FileData)
{
if (string.IsNullOrEmpty(fileData.Headers.ContentDisposition.FileName))
{
return Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted");
}
string fileName = fileData.Headers.ContentDisposition.FileName;
if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
{
fileName = fileName.Trim('"');
}
if (fileName.Contains(#"/") || fileName.Contains(#"\"))
{
fileName = Path.GetFileName(fileName);
}
File.Move(fileData.LocalFileName, Path.Combine(root, fileName));
}
return new HttpResponseMessage()
{
Content = new StringContent("Files uploaded.")
};
}
);
return task;
}
But I am not sure how to call it and pass file in a client app.
static string UploadEnvelope(string filePath, string token, string url)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
// How to pass file here ???
var response = client.GetAsync(url + "/api/Envelope/UploadEnvelope").Result;
return response.Content.ReadAsStringAsync().Result;
}
}
Any help or suggestion is welcome. Thanks in advance!
First you are using Get method which is used for reading. You have to use Post instead.
Try the following:
public static string UploadEnvelope(string filePath,string token, string url)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
using (var content = new MultipartFormDataContent("Envelope" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
{
content.Add(new StreamContent(new MemoryStream(File.ReadAllBytes(filePath))), "filename", "filename.ext");
using (var message = await client.PostAsync(url + "/api/Envelope/UploadEnvelope", content))
{
var input = await message.Content.ReadAsStringAsync();
return "success";
}
}
}
}
Note: For a large file you have to change configuration on IIS web.config.
In my ASP.NET MVC project, I am trying to post image from Controller action method to API controller method. Plan is to leverage this API to other clients to use to upload images.
I am able to successfully hit the API Post method from Controller Action method, but am not able to pass the image object.
Here is my HomeController.cs Upload Action Method
[HttpPost]
public async Task<ActionResult> Upload(FormCollection formCollection)
{
var baseUri = "http://localhost/api/Process";
HttpPostedFileBase file = Request?.Files[0];
if (file == null || (file.ContentLength <= 0) || string.IsNullOrEmpty(file.FileName))
return new EmptyResult();
string fileName = file.FileName;
byte[] fileBytes = new byte[file.ContentLength];
HttpContent stringContent = new StringContent(fileName);
HttpContent fileStreamContent = new StreamContent(file.InputStream);
HttpContent bytesContent = new ByteArrayContent(fileBytes);
using (var formDataContent = new MultipartFormDataContent())
{
formDataContent.Add(stringContent, "fileName", fileName);
formDataContent.Add(fileStreamContent, "inputStream", fileName);
formDataContent.Add(bytesContent, "fileBytes", fileName);
using (var httpClient = new HttpClient())
{
formDataContent.Headers.ContentType =
MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
var response = await httpClient.PostAsync(baseUri, formDataContent);
var content = await response.Content.ReadAsStringAsync();
//Handle the response
}
}
return View("Result");
}
In my Process controller which is inheriting from ApiController, I have the following Post method
[HttpPost]
public async Task<string> Post([FromBody]MultipartFormDataContent formDataContent)
{
Task<string> imageContent = Request.Content.ReadAsStringAsync();
string body = imageContent.Result;
ImageResponse imageResponse = null;
//.................
//.................
return someValue
}
Here parameter formDataContent is always null and Request.Content.ReadAsStringAsync() is empty
Try sending from the Controller like this
//...other code removed for brevity
using (var form = new MultipartFormDataContent()) {
var stringContent = new StringContent("fileToUpload");
form.Add(stringContent, "fileToUpload");
var streamContent = new StreamContent(file.InputStream);
streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(file.ContentType);
streamContent.Headers.ContentLength = file.ContentLength;
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {
Name = "fileToUpload",
FileName = file.FileName
};
form.Add(streamContent);
using (var httpClient = new HttpClient()) {
var response = await httpClient.PostAsync(baseUri, form);
//...other code removed for brevity
}
}
And then process it in the ApiController by extracting the information sent ...
[HttpPost]
public async Task<IHttpActionResult> Post() {
var content = Request.Content;
//get file name from content disposition
var fileName = content.Headers.ContentDisposition.FileName;
//Get file stream from the request content
var fileStream = await content.ReadAsStreamAsync();
//...other code removed for brevity
return Ok();
}
Referenced this answer : Upload image using HttpClient
I want implement api that upload zip files.
My function working for text files but not for zip file.
Zip file is saved but can not be open.
Do you know whet is good aproach for this?
At client I call api in next action:
[HttpPost]
public async Task<IActionResult> Upload(ICollection<IFormFile> files)
{
using (var client = new HttpClient())
{
foreach (var file in files)
{
if (file.Length > 0)
{
var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fileContent = new StreamContent(file.OpenReadStream());
fileContent.Headers.Add("X-FileName", fileName);
fileContent.Headers.Add("X-ContentType", file.ContentType);
var response = await client.PostAsync(url2, fileContent);
}
}
}
return View(nameof(this.Index));
}
This is my api:
[HttpPost]
public async Task<IActionResult> Post()
{
var input = new StreamReader(Request.Body).ReadToEnd();
var fileName = Request.Headers["X-FileName"];
var fileType = Request.Headers["X-ContentType"];
using (var sw = new StreamWriter(#"C:\" + fileName))
{
sw.Write(input);
}
await Task.FromResult(0);
return new ObjectResult(true);
}
This is my solutin:
On client API
[HttpPost("{lastModified}")]
public async Task<string> Upload(long lastModified)
{
using (var client = new HttpClient())
{
foreach (var file in Request.Form.Files)
{
if (file.Length > 0)
{
var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fileContent = new StreamContent(file.OpenReadStream());
var archiveUrl = "path to api with 2 parameters {fileName}/{lastModified}";
var datasetResponse = await client.PostAsync(archiveUrl, fileContent);
var dataset = await datasetResponse.Content.ReadAsStringAsync();
return dataset;
}
}
throw new ApplicationException("Cannot updated dataset to archive");
}
}
On server API
[HttpPost("{fileName}/{lastModified}")]
public async Task<IActionResult> Post(string fileName, long lastModified)
{
var dataSet = getDataSet();
return new ObjectResult(dataSet);
}