ASP.NET Core: Fetch image from external site and save on Server - image

I want to fetch an image from an external site and save it on the web applicationĀ“s server.
My current code downloads the file, but it won't open because of wrong format, it says.
private Uri _uri;
private HttpClient _client;
[HttpPost]
public async Task WmsExport(ExportImagePostData postData)
{
try
{
PrepareUri(postData);
ValidateUrl(postData);
PrepareRequest(postData);
await FetchImageAndSave_async(postData);
}
catch (TaskCanceledException)
{
HttpContext.Response.StatusCode = 408;
}
catch (Exception ex)
{
var statusCode = 500;
HttpContext.Response.StatusCode = statusCode;
_logger.LogError(ex, ex.Message);
}
}
private void PrepareRequest(ExportImagePostData postData)
{
_client = _customClientFactory.CreateHttpClient();
_client.BaseAddress = _uri;
_client.CopyRequestHeaders(HttpContext);
_client.DefaultRequestHeaders.Add("Accept", "image/png");
}
public async Task FetchImageAndSave_async(ExportImagePostData postData)
{
using (var contentStream = await _client.GetStreamAsync(_client.BaseAddress.OriginalString))
{
await SaveImageOnServer_async(postData, contentStream);
}
}
private async Task SaveImageOnServer_async(ExportImagePostData postData, Stream downloadStream)
{
var filename = "wmsexp" + DateTime.Now.ToString("HHmm") + "." + postData.ImageType;
var directory = "wwwroot/Images/uploads/";
var path = Path.Combine(Directory.GetCurrentDirectory(), directory, filename);
using (var outStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 1048576, true))
{
await downloadStream.CopyToAsync(outStream);
}
}
Here is how the images look like in my folder, when I try to open them:
****SOLVED** **
I got help from Roman Marusyk, here on Stack Overflow. Thanks Roman! If you write an answer I be happy to set it as the answer!
The issue seem to have been that I added wrong HTTP-headers, and that some of my paths to the images where incorrect.

Related

Puppeteer LaunchAsync throwing exception

I have an existing ASPNET Web Application. The front end is HTML/JavaScript and the backend is WebAPI 2. We have been using NRECO.PDFGenerator to drop PDFs to the users, this uses a the QT browser and debugging is becoming a chore. I found PuppeteerSharp and figured I'd give it a try.
I installed the libs using nuget, added an Async method to one of my Web Api Controllers but when I call it the LaunchAsync method just crashed.
[Route("api/pdf/v2/download")]
public IHttpActionResult V2Download([FromBody] Models.PDF.List _pdf) {
Models.Message.Response _return = new Models.Message.Response();
_return.Message = "Success!";
_return.Now = DateTime.Now;
try
{
string[] argu = null;
Meh(argu);
}
catch (Exception ex)
{
_return.Message = ex.Message;
_return.Severity = 3;
}
return Ok(_return);
}
public static async Task Meh(string[] args)
{
var options = new LaunchOptions
{
Headless = true,
Args = new[] {"--no-sandbox" }
};
Debug.WriteLine("Downloading chromium");
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
Debug.WriteLine("Navigating google");
using (var browser = await Puppeteer.LaunchAsync(options))
using (var page = await browser.NewPageAsync())
{
Debug.WriteLine("Navigating to page");
await page.GoToAsync("http://www.google.com");
Debug.WriteLine("Generating PDF");
await page.PdfAsync(Path.Combine(Directory.GetCurrentDirectory(), "google.pdf"));
Debug.WriteLine("Export completed");
if (!args.Any(arg => arg == "auto-exit"))
{
Console.ReadLine();
}
}
}
I'm not sure where to go from here. This is the console output. There's more...
Navigating google
The thread 0x3418 has exited with code 0 (0x0).
Exception thrown: 'System.NullReferenceException' in System.Web.dll
Exception thrown: 'System.NullReferenceException' in mscorlib.dll
The project is using framework 4.7.2
Solution
Everything that touches the Async method needs to also be Async. Also, Passing null args will cause problems as well.
Here's a code sample.
//[Authorize]
[Route("api/pdf/v2/download")]
public async Task<IHttpActionResult> V2Download([FromBody] Models.PDF.List _pdf) {
Models.Message.Response _return = new Models.Message.Response();
_return.Message = "Success!";
_return.Now = DateTime.Now;
try
{
string[] argu = { };
await Meh(argu);
}
catch (Exception ex)
{
_return.Message = ex.Message;
_return.Severity = 3;
}
return Ok(_return);
}
public static async Task Meh(string[] args)
{
var options = new LaunchOptions
{
Headless = true
};
Debug.WriteLine("Downloading chromium");
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
Debug.WriteLine("Navigating google");
using (var browser = await Puppeteer.LaunchAsync(options))
using (var page = await browser.NewPageAsync())
{
Debug.WriteLine("Navigating to page");
await page.GoToAsync("http://www.google.com");
Debug.WriteLine("Generating PDF");
await page.PdfAsync(Path.Combine(Directory.GetCurrentDirectory(), "google.pdf"));
Debug.WriteLine(Path.Combine(Directory.GetCurrentDirectory(), "google.pdf"));
Debug.WriteLine("Export completed");
if (!args.Any(arg => arg == "auto-exit"))
{
Console.ReadLine();
}
}
}

TaskContinuation.cs not found exception while accessing WebAPI Task

I'm trying to fetch records from a db cursor from the Client app.
Debugging Web API shows that the Cursor returns records but when returning to the Client it throws mscorlib.pdb not loaded window and clicking on Load option it throws TaskContinuation.cs not found exception
Code snippets as below ( removed irrelevant codes for readability )
WebAPI
[HttpPost("{values}")]
public async Task<ActionResult> Post([FromBody] JToken values)
{
// code removed for readility
string[] cursors = { };
cursors = await cursor.GetRpts();
CursorClass firstCursor = JsonConvert.DeserializeObject<CursorClass>(cursors[0]);
return new OkObjectResult(cursors);
}
public async Task<string[]> GetRpts()
{
try
{
DataTable[] dataTables;
CursorClass[] cursorClasses = new CursorClass[5];
//stripped some code
using (DataAccess dataAccess = new DataAccess()
{
ParamData = PrepareDoc(),
ProcedureName = Constants.Rpt,
RecordSets = this.CursorNumbers,
})
{
Int32 errorNumber = await dataAccess.RunComAsync();
dataTables = dataAccess.TableData;
};
//fetching code stripped off
string[] _cursors = Array.ConvertAll(cursorClasses, JsonConvert.SerializeObject);
return _cursors;
}
catch (Exception ex)
{
string tt = ex.Message;
}
}
public async Task<Int32> RunComAsync()
{
Int32 returnValue = 0;
try
{
//open db connection
//---------- Running the Command in asysnc mode ----------
Task<int> task = new Task<int>(oracleCommand.ExecuteNonQuery);
task.Start();
returnValue = await task;
//--------------------------------------------------------
OracleRefCursor[] refCursor = { null, null, null, null, null };
for (int _sub = 0; _sub < RecordSets; _sub++)
{
//DT declaration / connection code removed
dataAdapter.Fill(dataTable, refCursor[_sub]);
TableData[_sub] = dataTable;
}
}
catch (Exception ex)
{
return LogMsg(ex);
}
finally
{
this.Dispose(true);
}
CloseConnection();
return LogMsg(null,"Successful Operation");
}
Client
private async Task<HttpStatusCode> CallService()
{
HttpResponseMessage _response = null;
try
{
using (HttpRequestMessage requestMessage = new HttpRequestMessage()
{
Content = new System.Net.Http.StringContent(JsonRepo, System.Text.Encoding.UTF8, HeaderJson),
RequestUri = new Uri(UriString),
Method = HttpMethod.Post,
})
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", Utils.TOKEN) ;
_response = await httpClient.SendAsync(requestMessage);
if (_response.IsSuccessStatusCode)
{
string httpResponse = await _response.Content.ReadAsStringAsync();
httpString = JsonConvert.DeserializeObject<string[]>(httpResponse);
}
}
}
return ErrorCode;
}
Is that something related to async operation? while debugging the API it confirms the Datatable with records . Any inputs are deeply appreciated.
error image
TIA

Best practice to send a lot of files (images) from your device to your server

I have a list of files to send from my device to my server.
List<myFiles> list = new List<myFiles>() { "[long list of files...]" };
For that I want to create a list of tasks: for each file I should invoke a function that sends to my webapi that file via PUT
public async Task<bool> UploadPhoto(byte[] photoBytes, int PropertyId, string fileName)
{
bool rtn = false;
if (CrossConnectivity.Current.IsConnected)
{
var content = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(photoBytes);
fileContent.Headers.ContentType =
MediaTypeHeaderValue.Parse("multipart/form-data");
fileContent.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = fileName + ".jpg"
};
content.Add(fileContent);
string url = RestURL() + "InventoriesPicture/Put";
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("authenticationToken", SyncData.Token);
HttpResponseMessage response = await client.PutAsync(url, content);
if (response.IsSuccessStatusCode)
{
rtn = true;
Debug.WriteLine($"UploadPhoto response {response.ReasonPhrase}");
}
else
{
Debug.WriteLine($"UploadPhoto response {response.ReasonPhrase}");
}
}
}
catch (Exception ex)
{
Debug.WriteLine($"UploadPhoto exception {ex.Message}");
}
Debug.WriteLine($"UploadPhoto ends {fileName}");
}
return rtn;
}
In a function I have a foreach that calls UploadPhoto. I think there are too many tasks at the same time then I want to send a file, wait the result from the webapi and then send next file and so on.
What can I do? What is the best practice for that? Or in any case how can I resolve my problem? :)
Thank you in advance

while streaming video file, file is getting locked by another process using PushStreamContent..how to solve it

I am trying to stream video file . when i open the same video file in another tab of browser , i get the message "file is being used by another process" . if I use FileShare.ReadWrite in file.open method then error goes away but video doesn't play in browser . can someone pl. help .
public HttpResponseMessage Get([string id)
{
var path = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["path"] + "/" + id);
var video = new VideoStream(path);
HttpResponseMessage response = Request.CreateResponse();
var contentType = ConfigurationManager.AppSettings[Path.GetExtension(id)];
response.Content = new PushStreamContent(video.WriteToStream, new MediaTypeHeaderValue(contentType));
return response;
}
public class VideoStream
{
private readonly string _filename;
public VideoStream(string filename)
{
_filename = filename;
}
public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
{
try
{
var buffer = new byte[65536];
using (var video = File.Open(_filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
var length = (int) video.Length;
var bytesRead = 1;
while (length > 0 && bytesRead > 0)
{
bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
await outputStream.WriteAsync(buffer, 0, bytesRead);
length -= bytesRead;
video.Flush();
}
}
}
catch (HttpException ex)
{
return;
}
finally
{
// outputStream.Close();
// outputStream.Flush();
}
}
}
You should use:
File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read);
Assuming the file lock comes from the server. Is that the case, or is it a client side thing?

when try to download a mp3 ;an error occur "The remote server returned an error: NotFound."

when i down load the two same link like those
a link! and http://files.sparklingclient.com/099_2010.07.09_WP7_Phones_In_The_Wild.mp3
they all can be downloded by IE .but when i download in wp7 the laster can be downloaded the first show an error ""The remote server returned an error: NotFound.""
i don't konw why .is webURL is not suited for wp7?
private void Button_Click(object sender, RoutedEventArgs e)
{
stringUri = "http://upload16.music.qzone.soso.com/30828161.mp3";
//stringUri = "http://files.sparklingclient.com/079_2009.08.20_ElementBinding.mp3";
Uri uri = new Uri(stringUri, UriKind.Absolute);
GetMusic(uri);
}
private void GetMusic(Uri uri)
{
request = WebRequest.Create(uri) as HttpWebRequest;
request.Method = "Post";
request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
string header= request.Accept;
request.BeginGetResponse(new AsyncCallback(GetAsynResult),request);
}
void GetAsynResult(IAsyncResult result)
{
HttpWebResponse reponse = request.EndGetResponse(result) as HttpWebResponse;
if (reponse.StatusCode == HttpStatusCode.OK)
{
Stream stream=reponse.GetResponseStream();
SaveMusic(stream, "music");
ReadMusic("music");
Deployment.Current.Dispatcher.BeginInvoke(
() =>
{
me.AutoPlay = true;
me.Volume = 100;
songStream.Position = 0;
me.SetSource(songStream);
me.Play();
});
}
}
protected void SaveMusic(Stream stream,string name)
{
IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (!fileStorage.DirectoryExists("Source/Music"))
{
fileStorage.CreateDirectory("Source/Music");
}
using (IsolatedStorageFileStream fileStream = IsolatedStorageFile.GetUserStoreForApplication().OpenFile("Source\\Music\\" + name + ".mp3", FileMode.Create))
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Flush();
}
}
protected void ReadMusic(string name)
{
using (IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
songStream = null;
songStream = new IsolatedStorageFileStream("Source\\Music\\" + name + ".mp3", FileMode.Open, fileStorage);
}
}
Please try to change
request.Method = "Post"
to
request.Method = "Get"
If you are running into this problem on the emulator, have you tried running Fiddler? It will intercept the HTTP requests and you can see if the call being made to the server is the one you expect.
Remember to close/reopen the emulator after you start Fiddler so that it will pick up the proxy.
The NotFound response can also occur with bad SSL certificates. That doesn't appear to be related to your problem, but something to keep in mind.

Resources