I followed the video tutorial Houssem Dellai about Upload File from Xamarin app to ASP.NET server on youtube.
here is the link https://www.youtube.com/watch?v=IVvJX4CoLUY
My problem when i click button upload photo my code is only executed until
var httpResponseMessage = await httpclient.PostAsync(uploadServiceBaseAddress, content);
And didn't show message error, my code cannot executed RemotePathFile.Text for show path file
This is my coding
private async void UploadFile_Clicked(object sender, EventArgs e)
{
var content = new MultipartFormDataContent();
content.Add(new StreamContent(_mediaFile.GetStream()),
"\"file\"",
$"\"{_mediaFile.Path}\"");
var httpclient = new HttpClient();
var uploadServiceBaseAddress = "https://192.168.43.172/api/Files/Upload";
var httpResponseMessage = await httpclient.PostAsync(uploadServiceBaseAddress, content);
RemotePathFile.Text = await httpResponseMessage.Content.ReadAsStringAsync();
}
And This is my UploadController
public class UploadsController : ApiController
{
[Route("api/Files/Upload")]
public async Task<string> Post()
{
try
{
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var fileName = postedFile.FileName.Split('\\').LastOrDefault().Split('/').LastOrDefault();
var filePath = HttpContext.Current.Server.MapPath("~/Uploads/" + fileName);
postedFile.SaveAs(filePath);
return "/Uploads/" + fileName;
}
}
}
catch (Exception exception)
{
return exception.Message;
}
return "no files";
}
}
Please help me, how i can fix ?
Related
I'm trying to add a new function where user can upload images and videos similar to facebook in blazor server .NET 6, I created a new api and followed microsoft documentation of uploading files, Everything is working so far with uploading up to 4 files, but when I'm trying to upload more than 4 it doesn't send a request to the api at all. and after a while it shows these two exceptionsenter image description here enter image description here
Here's the code I'm having: `
private List<File> files = new();
private List<UploadInfo> uploadResults = new();
private int maxAllowedFiles = 10;
private bool shouldRender;
protected override bool ShouldRender() => shouldRender;
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
shouldRender = false;
long maxFileSize = (long)(4 * Math.Pow(10, 8));
var upload = false;
using var content = new MultipartFormDataContent();
foreach (var file in e.GetMultipleFiles(maxAllowedFiles))
{
if (uploadResults.SingleOrDefault(
f => f.FileName == file.Name) is null)
{
try
{
var fileContent =
new StreamContent(file.OpenReadStream(maxFileSize));
fileContent.Headers.ContentType =
new MediaTypeHeaderValue(file.ContentType);
files.Add(new() { Name = file.Name });
content.Add(
content: fileContent,
name: "\"files\"",
fileName: file.Name);
upload = true;
}
catch (Exception ex)
{
Logger.LogInformation(
"{FileName} not uploaded (Err: 6): {Message}",
file.Name, ex.Message);
uploadResults.Add(
new()
{
FileName = file.Name,
ErrorCode = 6,
Uploaded = false
});
}
}
}
if (upload)
{
var client = ClientFactory.CreateClient();
var response =
await client.PostAsync($"https://localhost:7134/api/Files/FileUpload", content);
if (response.IsSuccessStatusCode)
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
using var responseStream =
await response.Content.ReadAsStreamAsync();
var newUploadResults = await JsonSerializer
.DeserializeAsync<IList<MediaAPI.UploadInfo>>(responseStream, options);
if (newUploadResults is not null)
{
uploadResults = uploadResults.Concat(newUploadResults).ToList();
}
}
}
shouldRender = true;
}`
When I try to debug it, the debug point disappears when it sends the request:
await client.PostAsync($"https://localhost:7134/api/Files/FileUpload", content);
Anyone has experiansed this issue before?
Thanks in advance.
I'm trying to save an image that comes from Xamarin forms Android but the method Post doesn't get the image, but the image reaches the page.
Xamarin code:
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("No pick photo", "no pick photo available", "OK");
}
_mediaFile = await CrossMedia.Current.PickPhotoAsync();
if (_mediaFile == null)
return;
lblStatus.Text = _mediaFile.Path;
var content = new MultipartFormDataContent();
content.Add(new StreamContent(_mediaFile.GetStream()), "\"file\"",
$"\"{_mediaFile.Path}\"");
var httpClient = new HttpClient();
var uploadServiceBaseAddress = "http://url/api/Files/Upload";
var httpResponseMessage = await httpClient.PostAsync(uploadServiceBaseAddress, content);
lblStatus.Text = await httpResponseMessage.Content.ReadAsStringAsync();
ASP.NET Core MVC / C# code:
[Route("api/Files/Upload")]
public async Task<string> Post(List<IFormFile> files)
{
try
{
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
var fileName = formFile.FileName.Split('\\').LastOrDefault().Split('/').LastOrDefault();
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "~/Uploads/", fileName);
using (var stream = System.IO.File.Create(filePath))
{
await formFile.CopyToAsync(stream);
}
return "/Uploads/" + fileName;
}
}
}
catch (Exception exception)
{
return exception.Message;
}
return "no files";
}
In my mobile app return "no files", so the image is not saved in the folder.
Does someone know why that is?
Thank you very much!
I found the solution. I leave my code in case it helps someone. I just had to change these lines
[Route("api/Files/Upload")]
public async Task<string> Post()
{
try
{
var fileName = this.Request.Form.Files[0].FileName.Split('\\').LastOrDefault().Split('/').LastOrDefault();
var filePath = Path.Combine(Directory.GetCurrentDirectory(), #"wwwroot\Uploads\", fileName);
using (var stream = System.IO.File.Create(filePath))
{
await this.Request.Form.Files[0].CopyToAsync(stream);
}
return "/Uploads/" + fileName;
}
catch (Exception exception)
{
return exception.Message;
}
return "no files";
}
Now I have configured for UWP photo post to web api part which is using HttpClient.
Uri uri = new Uri("http://localhost:50040/api/Upload");
IInputStream inputStream = await photoFile.OpenAsync(FileAccessMode.Read);
HttpMultipartFormDataContent multipartContent = new HttpMultipartFormDataContent();
multipartContent.Add(new HttpStreamContent(inputStream), "myFile", photoFile.Name);
Windows.Web.Http.HttpClient newclient = new Windows.Web.Http.HttpClient();
Windows.Web.Http.HttpResponseMessage response = await client.PostAsync(uri, multipartContent);
But I don't know how to set for the server side which is my .NET core web api to get the image which post from my UWP application.Please Help me, thank you.
But I don't know how to set for the server side which is my .NET core web api
Please reference the File uploads official tutorial to create your server side. For example, add POST method as following sample code showed to receive the UWP client sent file with the client code you showed above.
// POST api/values
[HttpPost]
public async Task<IActionResult> Post(IFormFile myFile)
{
// full path to file in temp location, you could change this
var filePath = Path.GetTempFileName();
if (myFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await myFile.CopyToAsync(stream);
}
}
// process uploaded files
// Don't rely on or trust the FileName property without validation.
return Ok(new { filePath, myFile.Length });
}
More details you could also reference the official sample.
In Web API Controller
public IHostingEnvironment _environment;
public UploadFilesController(IHostingEnvironment environment) // Create Constructor
{
_environment = environment;
}
[HttpPost("UploadImages")]
public Task<ActionResult<string>> UploadImages([FromForm]List<IFormFile> allfiles)
{
string filepath = "";
foreach (var file in allfiles)
{
string extension = Path.GetExtension(file.FileName);
var upload = Path.Combine(_environment.ContentRootPath, "ImageFolderName");
if (!Directory.Exists(upload))
{
Directory.CreateDirectory(upload);
}
string FileName = Guid.NewGuid() + extension;
if (file.Length > 0)
{
using (var fileStream = new FileStream(Path.Combine(upload, FileName), FileMode.Create))
{
file.CopyTo(fileStream);
}
}
filepath = Path.Combine("ImageFolderName", FileName);
}
return Task.FromResult<ActionResult<string>>(filepath);
}
In yourpage.xaml.cs
using Windows.Storage;
using Windows.Storage.Pickers;
.....
StorageFile file;
......
private async void btnFileUpload_Click(object sender, RoutedEventArgs e) // Like Browse button
{
try
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".png");
file = await openPicker.PickSingleFileAsync();
if (file != null)
{
//fetch file details
}
}
catch (Exception ex)
{
}
}
//When upload file
var http = new HttpClient();
var formContent = new HttpMultipartFormDataContent();
var fileContent = new HttpStreamContent(await file.OpenReadAsync());
formContent.Add(fileContent, "allfiles", file.Name);
var response = await http.PostAsync(new Uri("Give API Path" + "UploadImages", formContent);
string filepath = Convert.ToString(response.Content); //Give path in which file is uploaded
Hope this code helps you...
But remember formContent.Add(fileContent, "allfiles", file.Name); line is important and allfiles is that name of parameter to fetch files in web api method "public Task<ActionResult<string>> UploadImages([FromForm]List<IFormFile> **allfiles**)"
Thanks!!!
I am trying to call the Web api method for saving the File Data.When I debug Webapi method I found that ContentLength is not coming as correct, because of this when i am retrieving the file it is showing error as corrupted file.
My Class method is :-
using (var formData = new MultipartFormDataContent())
{
HttpContent stringContent = new StringContent(file);
formData.Add(stringContent, "file", file);
formData.Add(new StringContent(JsonConvert.SerializeObject(file.Length)), "ContentLength ");
HttpResponseMessage responseFile = client.PostAsync("Report/SaveFile?docId=" + docId, formData).Result;
}
My Web api method is :-
[HttpPost]
public HttpResponseMessage SaveFile(long docId)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Unauthorized);
try
{
var httpRequest = HttpContext.Current.Request;
bool IsSuccess = true;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
HttpPostedFile postedFile = httpRequest.Files[file];
// Initialize the stream.
Stream myStream = postedFile.InputStream;
myStream.Position = 0;
myStream.Seek(0, SeekOrigin.Begin);
var _item = CorrectedReportLibrary.Services.ReportService.SaveFile(myStream,docId);
response = Request.CreateResponse<bool>((IsSuccess)
? HttpStatusCode.OK
: HttpStatusCode.NoContent,
IsSuccess);
}
}
}
catch (Exception ex)
{
Theranos.Common.Library.Util.LogManager.AddLog(ex, "Error in CorrectedReportAPI.Controllers.SaveDocument()", null);
return Request.CreateResponse<ReportDocumentResult>(HttpStatusCode.InternalServerError, null);
}
return response;
}
How can I set the ContentLength from C# class method?
It looks a bit strange that you use ContentLength as the second parameter on the StringContent class. It is suppose to be which encoding you want to use, for example
new StringContent(content, Encoding.UTF8). I don't think it is the content length that is the issue here.
StringContent class
I guess since it is a file you want to upload, you already have the file read as a stream, so I usually do something like this:
Client:
private async Task UploadFile(MemoryStream file)
{
var client = new HttpClient();
var content = new MultipartFormDataContent();
content.Add(new StreamContent(file));
var result = await client.PostAsync("Report/SaveFile?docId=" + docId, content);
}
Edit. Since it's a multipartform it's easier to let the framework handle the details. Try something like this:
Server:
[HttpPost]
public async Task<HttpResponseMessage> SaveFile(long docId)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Unauthorized);
try
{
var filedata = await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider());
foreach(var file in filedata.Contents)
{
var fileStream = await file.ReadAsStreamAsync();
}
response = Request.CreateResponse<bool>(HttpStatusCode.OK, true);
}
catch (Exception ex)
{
response = Request.CreateResponse<bool>(HttpStatusCode.InternalServerError, false);
}
return response;
}
At Last I found the solution no need to change the web api service,
issue was from client where I was directly passing the file data, Now the modified
working code is like this:-
using (var formData = new MultipartFormDataContent())
{
var bytes = File.ReadAllBytes(file);
formData.Add(new StreamContent(new MemoryStream(bytes)), "file", file);
HttpResponseMessage responseFile = client.PostAsync("ReportInfo/SaveFile?docId=" + docId, formData).Result;
}
I'm trying to upload files in a WPF-application. Everything works fine if the server responds but the application will be used in an environment with "unsafe" internet connection. So I want to retry uploading after a short break if the first attempt failed.
I tried several things with async/await and ended up with the following code.
If the server is running everything is fine, but if not the program fails with an ObjectDisposedException in the second iteration of the while-loop.
Any ideas?
private void UploadButton_Click(object sender, RoutedEventArgs e)
{
// build content to send
content = new MultipartFormDataContent();
var filestream = new FileStream(filePath, FileMode.Open);
var fileName = System.IO.Path.GetFileName(filePath);
content.Add(new StreamContent(filestream), "file", fileName);
content.Add(new StringContent(terminal_id.ToString()), "terminal_id");
UploadTask(content);
/*var task_a = new Task(() => UploadTask(content));
task_a.Start();*/
}
private async void UploadTask(HttpContent content)
{
bool success = false;
int counter = 0;
while (counter < 3 && !success)
{
Debug.WriteLine("starting upload");
success = await UploadFileAsync(content);
Debug.WriteLine("finished upload. result " + success.ToString());
//if (!success) System.Threading.Thread.Sleep(5000);
counter++;
}
}
private async Task<bool> UploadFileAsync(HttpContent content)
{
var message = new HttpRequestMessage();
message.Method = HttpMethod.Post;
message.Content = content;
message.RequestUri = new Uri(target_url);
using (HttpClient client = new HttpClient())
{
try
{
HttpResponseMessage res = await client.SendAsync(message);
if (res.IsSuccessStatusCode) return true;
}
catch (HttpRequestException hre)
{
Debug.WriteLine(hre.ToString());
}
return false;
}
}
Seems like your file stream gets disposed/closed. You need to retry from the very beginning (content = new MultipartFormDataContent(); etc).
I think issue could be that the content is going out of scope? Try creating content inside the UploadTask method. Also, it might be worth returning a Task<bool> from UploadTask and caching it is a class level variable (so you don't have to return void).
For example:
Task<bool> newTask;
private void UploadButton_Click(object sender, RoutedEventArgs e)
{
newTask = UploadTask();
}
private async Task<bool> UploadTask()
{
bool success = false;
int counter = 0;
// build content to send
HttpContent content = new MultipartFormDataContent();
var filestream = new FileStream(filePath, FileMode.Open);
var fileName = System.IO.Path.GetFileName(filePath);
content.Add(new StreamContent(filestream), "file", fileName);
content.Add(new StringContent(terminal_id.ToString()), "terminal_id");
while (counter < 3 && !success)
{
Debug.WriteLine("starting upload");
success = await UploadFileAsync(content);
Debug.WriteLine("finished upload. result " + success.ToString());
counter++;
}
return success;
}
After moving the creation of the content into UploadFileAsync() it works. Result:
Task<bool> newTask;
private void UploadButton_Click(object sender, RoutedEventArgs e)
{
newTask = UploadTask();
}
private async Task<bool> UploadTask()
{
bool success = false;
int counter = 0;
while (counter < 3 && !success)
{
Debug.WriteLine("starting upload");
success = await UploadFileAsync();
Debug.WriteLine("finished upload. result " + success.ToString());
if (!success) System.Threading.Thread.Sleep(5000);
counter++;
}
return success;
}
private async Task<bool> UploadFileAsync()
{
MultipartFormDataContent content = new MultipartFormDataContent();
var filestream = new FileStream(filePath, FileMode.Open);
var fileName = System.IO.Path.GetFileName(filePath);
content.Add(new StreamContent(filestream), "file", fileName);
content.Add(new StringContent(terminal_id.ToString()), "terminal_id");
var message = new HttpRequestMessage();
message.Method = HttpMethod.Post;
message.Content = content;
message.RequestUri = new Uri(target_url);
using (HttpClient client = new HttpClient())
{
try
{
HttpResponseMessage res = await client.SendAsync(message);
if (res.IsSuccessStatusCode) return true;
}
catch (HttpRequestException hre)
{
Debug.WriteLine(hre.ToString());
}
return false;
}
}