How to download a file with Puppeteer Sharp? - puppeteer-sharp

Here is the code that works but it doesn't wait until the completion. How do I make sure the file has been saved?
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
ExecutablePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
Headless = false,
});
var page = (await browser.PagesAsync()).First();
page.Response += async (object sender, ResponseCreatedEventArgs e) =>
{
if (e.Response.Url.Contains(".mp4"))
{
byte[] buff = await e.Response.BufferAsync();
File.WriteAllBytes($"{DateTime.UtcNow.ToFileTime()}.mp4", buff);
}
};
await page.GoToAsync("https://file-examples-com.github.io/uploads/2017/04/file_example_MP4_480_1_5MG.mp4");
await Task.Delay(30000);

Here, just wrote it:
public static async Task<FileInfo> DownloadFileAsync(string url)
{
try
{
await _page.GoToAsync(url);
}
catch (NavigationException)
{
// Trying to open a file page throws navigation exception, should be ignored
}
await _page.WaitForNetworkIdleAsync();
while (Directory.GetFiles(_downloadDirectory, "*.crdownload", SearchOption.AllDirectories).Length > 0)
{
await Task.Delay(250);
}
for (int i = 0; i < 100; i++)
{
var finishedFiles = (new DirectoryInfo(_downloadDirectory)).GetFiles();
var downloadedFile = finishedFiles.OrderByDescending(f => f.LastWriteTime).FirstOrDefault();
if (downloadedFile != null)
{
return downloadedFile!;
}
await Task.Delay(250);
}
throw new Exception($"Download failed for: {url}");
}

Related

How to upload images after cropping in Xamarin

I am using ImageCropper and MediaPlugin to Upload images. However I have problem getting the image after cropping the image.
string imagefile;
protected void OnClickedRectangle(object sender, EventArgs e)
{
new ImageCropper()
{
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
});
}
}.Show(this);
}
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var content = new MultipartFormDataContent();
content.Add(new StreamContent(imageFile), "files", imagefile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxx/api/Upload", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
However how can I get the Image to upload. note that view_imageavatar still shows the image after cropping. Tks!
Update...
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var fileStream = File.OpenRead(imageFile);
var fileContent = new StreamContent(fileStream);
var content = new MultipartFormDataContent();
content.Add(fileContent, "files", imageFile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
It still doesn't work?
Update 2
async void edit_avatar_Tapped(object sender, EventArgs e)
{
try
{
await CrossMedia.Current.Initialize();
new ImageCropper()
{
PageTitle = "Title",
AspectRatioX = 1,
AspectRatioY = 1,
CropShape = ImageCropper.CropShapeType.Rectangle,
SelectSourceTitle = "Img",
TakePhotoTitle = "Take Camera",
PhotoLibraryTitle = "Img Gallery",
Success = (imageFile) =>
{
Device.BeginInvokeOnMainThread(async() =>
{
view_imageavatar.Source = ImageSource.FromFile(imageFile);
imagefile = imageFile;
//API Get Images Upload
var upfilebytes = File.ReadAllBytes(imageFile);
var ms = new MemoryStream(upfilebytes);
var content = new MultipartFormDataContent();
content.Add(new StreamContent(ms), "files", imageFile);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
});
}
}.Show(this);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
}
}
-> It still can't upload photos through the API?
However I try not to use ImageCropper. I upload directly.
async void edit_avatar_Tapped(object sender, EventArgs e)
{
var file = await MediaPicker.PickPhotoAsync();
var content = new MultipartFormDataContent();
content.Add(new StreamContent(await file.OpenReadAsync()), "files", file.FileName);
var httpClient = new HttpClient();
var responses = await httpClient.PostAsync("https://xxxxxx/api/UploadAvatarUs", content);
string a = responses.StatusCode.ToString();
}
--> Then it works fine, the image is uploaded through the API
Does the image load from content.Add(new StreamContent(ms), "files", imageFile); it doesn't work with API? Looking for solutions from everyone.
Have you actually checked what StreamContent takes as arguments?
It takes a Stream not a path to a file.
You need to open the file first like so:
using var fileStream = File.Open(imageFile);
using var fileContent = new StreamContent(fileStream);
Have you tried something like that?

Xamarin Forms throws Plugin.Media.Abstractions.MediaPermissionException while taking photo

I am trying to capture an image/pick up an image from gallery in Xamarin Forms app. I have installed the nuget manager > Birdie.MediaPlugin. During On click on the button in the Register page throws below error;
Plugin.Media.Abstractions.MediaPermissionException: <Timeout exceeded getting exception details Could someone please advise where should we add persmission in Xamarin.Forms app ?
// Register.xaml:
<Image x:Name="imageDisplay" />
<Button x:Name="uploadButton"
Text="Upload Image" Clicked="UploadButton_Clicked"/>
// PlayerDetails.cs
public ImageSource Source { get; internal set; }
//Register.xaml.cs
PlayerDetails myDetails;
public Register(PlayerDetails playD)
{
InitializeComponent();
BindingContext = myDetails;
}
private async void UploadButton_Clicked(object sender, EventArgs e)
{
//myDetails.Image = new Image();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
return;
}
var status = await GetPermissions();
if(status == true)
{
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
Directory = "Sample",
Name = "flower1.jpg"
});
if (file == null)
return;
await DisplayAlert("File Location", file.Path, "OK");
myDetails.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
}
else
{
await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");
//On iOS you may want to send your user to the settings screen.
if (Device.RuntimePlatform == Device.iOS)
CrossPermissions.Current.OpenAppSettings();
}
}
//I have split the permission function as below;
public static async Task<bool> GetPermissions()
{
bool permissionsGranted = true;
var permissionsStartList = new List<Permission>()
{
Permission.Location,
Permission.LocationAlways,
Permission.LocationWhenInUse,
Permission.Storage,
Permission.Camera
};
var permissionsNeededList = new List<Permission>();
try
{
foreach (var permission in permissionsStartList)
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(permission);
if (status != PermissionStatus.Granted)
{
permissionsNeededList.Add(permission);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Nice, exception! " + ex);
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(permissionsNeededList.ToArray());
try
{
foreach (var permission in permissionsNeededList)
{
var status = PermissionStatus.Unknown;
//Best practice to always check that the key exists
if (results.ContainsKey(permission))
status = results[permission];
if (status == PermissionStatus.Granted || status == PermissionStatus.Unknown)
{
permissionsGranted = true;
}
else
{
permissionsGranted = false;
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Last, exception! " + ex);
}
return permissionsGranted;
}
You can update your OnClick event code to add the permissions logic as well:
var cameraStatus = await CrossPermissions.Current.CheckPermissionStatusAsync<CameraPermission>();
var storageStatus = await CrossPermissions.Current.CheckPermissionStatusAsync<StoragePermission>();
if (cameraStatus != PermissionStatus.Granted || storageStatus != PermissionStatus.Granted)
{
cameraStatus = await CrossPermissions.Current.RequestPermissionAsync<CameraPermission>();
storageStatus = await CrossPermissions.Current.RequestPermissionAsync<StoragePermission>();
}
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
return;
}
if (cameraStatus == PermissionStatus.Granted && storageStatus == PermissionStatus.Granted)
{
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
Directory = "Sample",
Name = "flower1.jpg"
});
if (file == null)
return;
await DisplayAlert("File Location", file.Path, "OK");
myDetails.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
}
else
{
await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");
//On iOS you may want to send your user to the settings screen.
if (Device.RuntimePlatform == Device.iOS)
CrossPermissions.Current.OpenAppSettings();
}
Note:It will become a long function so I recommend breaking it up into different functions.

Fail Implementing SqlBotDataStore

I have implemented SqlBotDataStore for bot storage but the LoadAsync method is silently failing. This is in the MessageController's POST. No exceptions are thrown anywhere, it just stops at this line, the chat bot continues as if nothing ever happened but storage does not work:
var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
var key = Address.FromActivity(activity);
try
{
var userData = await botDataStore.LoadAsync(key, BotStoreType.BotPrivateConversationData, CancellationToken.None);
userData.SetProperty<Translator>("translator", new Translator());
userData.SetProperty<bool>("autoDetectLanguage", true);
userData.SetProperty<bool>("autoTranslateToBot", true);
userData.SetProperty<bool>("autoTranslateToUser", true);
await botDataStore.SaveAsync(key, BotStoreType.BotPrivateConversationData, userData, CancellationToken.None);
}
catch (HttpException e)
{
Debug.WriteLine(e.Message);
}
I cannot seem to get past this and unfortunately don't have any more information because literally no error or anything happens here. When debugging it just never goes to the next line and continues execution silently.
Based on this github sample using Azure Sql Storage to store the bot state, I modify the sample with following updates and do a test, which work for me. You can compare the sample with your implementation to find differences.
In MessagesController:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
if (activity.Text == "savetest")
{
var message = activity as IMessageActivity;
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
var key = Address.FromActivity(activity);
try
{
var userData = await botDataStore.LoadAsync(key, BotStoreType.BotPrivateConversationData, CancellationToken.None);
//userData.SetProperty<Translator>("translator", new Translator());
userData.SetProperty<bool>("autoDetectLanguage", true);
userData.SetProperty<bool>("autoTranslateToBot", true);
userData.SetProperty<bool>("autoTranslateToUser", true);
await botDataStore.SaveAsync(key, BotStoreType.BotPrivateConversationData, userData, CancellationToken.None);
await botDataStore.FlushAsync(key, CancellationToken.None);
}
catch (HttpException e)
{
Debug.WriteLine(e.Message);
}
}
}
await Conversation.SendAsync(activity, () => new Dialogs.EchoDialog());
}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
In EchoDialog:
var tval = context.PrivateConversationData.GetValueOrDefault<bool>("autoTranslateToBot", false);
await context.PostAsync("You said: " + message.Text + $"; autoTranslateToBot is {tval.ToString()}");
context.Wait(MessageReceivedAsync);
Test result:

How to read cookie in nsIChannel?

const {Cc,Ci,Cr} = require("chrome");
function TracingListener() {
//this.receivedData = [];
}
function CCIN(cName, ifaceName) {
return Cc[cName].createInstance(Ci[ifaceName]);
}
function CCSV(cName, ifaceName){
if (Cc[cName])
// if fbs fails to load, the error can be _CC[cName] has no properties
return Cc[cName].getService(Ci[ifaceName]);
};
TracingListener.prototype =
{
originalListener: null,
receivedData: null, // array for incoming data.
onDataAvailable: function(request, context, inputStream, offset, count)
{
this.originalListener.onDataAvailable(request, context,inputStream, offset, count);
},
onStartRequest: function(request, context) {
this.receivedData = [];
this.originalListener.onStartRequest(request, context);
//thechannel.setRequestHeader("X-Hello", "World", false);
//this part of code will stop the request
/*request.QueryInterface(Ci.nsIHttpChannel);
var cookie=request.getRequestHeader("Cookie");
console.log("cookie="+cookie);*/
var postText = this.readPostTextFromRequest(request, context);
console.log("postText="+postText111);
},
onStopRequest: function(request, context, statusCode)
{
//this part of code will successfullly print the cookie
/*request.QueryInterface(Ci.nsIHttpChannel);
var cookie=request.getRequestHeader("Cookie");
console.log("cookie="+cookie);*/
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_NOINTERFACE;
},
readPostTextFromRequest : function(request, context) {
try
{
var is = request.QueryInterface(Ci.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Ci.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
}
// Read data from the stream..
var charset = "UTF-8";
var text = this.readFromStream(is, charset, true);
// Seek locks the file so, seek to the beginning only if necko hasn't read it yet,
// since necko doesn't seek to 0 before reading (at lest not till 459384 is fixed).
if (ss && prevOffset == 0)
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
//dump("Failed to Query Interface for upload stream.\n");
}
}
catch(exc)
{
//dumpError(exc);
}
return null;
},
readFromStream : function(stream, charset, noClose) {
var sis = CCSV("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
sis.setInputStream(stream);
var segments = [];
for (var count = stream.available(); count; count = stream.available())
segments.push(sis.readBytes(count));
if (!noClose)
sis.close();
var text = segments.join("");
return text;
}
}
hRO = {
observe: function(request, aTopic, aData){
try {
if (aTopic == "http-on-examine-response") {
request.QueryInterface(Ci.nsIHttpChannel);
//if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0) {
var newListener = new TracingListener();
request.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = request.setNewListener(newListener);
//}
}
} catch (e) {
/*dump("\nhRO error: \n\tMessage: " + e.message + "\n\tFile: " + e.fileName + " line: " + e.lineNumber + "\n");*/
}
},
QueryInterface: function(aIID){
if (aIID.equals(Ci.nsIObserver) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_NOINTERFACE;
},
};
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(hRO,
"http-on-examine-response", false);
My question is: the same lines of code:
request.QueryInterface(Ci.nsIHttpChannel);
var cookie=request.getRequestHeader("Cookie");
console.log("cookie="+cookie);
performs different results in onStartRequest and onStopRequest, why?
I can read the cookie in onStopRequest but fails in onStartRequest. I don't think the request is not ready in onStartRequest because I can read the postText in onStartRequest.

maxRequestLength in selfhost? File size>100kb will not upload

I encounter a problem that when upload file size large than 100kb, web api controller will not be called. I search for a while and found that maybe I should set maxRequestLength in webconfig. But how to set it in self host?
the client
public async Task<bool> Upload(DeviceFile file,string path)
{
var formData = new MultipartFormDataContent();
var request = new HttpRequestMessage();
var md5 = new MD5CryptoServiceProvider();
var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read,bufferSize:4096,useAsync:true);
fileStream.Position = 0;
var hash = md5.ComputeHash(fileStream);
fileStream.Position = 0;
formData.Add(
new StreamContent(fileStream),
file.Name,
file.Name,
new {
Info = file.Info,
}
);
request.Method = HttpMethod.Post;
request.Content = formData;
request.RequestUri = new Uri(client.BaseAddress,"api/file/");
try
{
var response = await client.SendAsync(request).ConfigureAwait(false);
await response.Content.ReadAsAsync<bool>().ConfigureAwait(false);
}
catch (Exception ex)
{
this.logger.Log(ex.ToString(), Category.Info, Priority.None);
}
return true;
}
the server controller
public async Task<HttpResponseMessage> Add()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = new MultipartFormDataStreamProvider("D:/");
try
{
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
Console.WriteLine(file.Headers.ContentDisposition.FileName);
Console.WriteLine("Server file path: " + file.LocalFileName);
}
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
Console.WriteLine(string.Format("{0}: {1}", key, val));
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
The MaxReceivedMessageSize can be set on the self-host config object.
http://msdn.microsoft.com/en-us/library/system.web.http.selfhost.httpselfhostconfiguration.maxreceivedmessagesize(v=vs.108).aspx#feedback

Resources