LiveSDK for Universal Windows App background upload - c#

I'm developing Universal Windows App and use Live SDK 5.6 to upload files to OneDrive. I see examples of usage here and instructions about versions here.
According to instructions I should use:
For Windows and WP81: CreateBackgroundUploadAsync method;
For WP8 Silverlight: BackgroundUploadAsync method
CreateBackgroundUploadAsync works like a charm on Windows and returns correct progress values by LiveOperationProgress but on a WP81 it shows 0% progress all the time and at last it becames 100%. So it actually does not track progress.
Then I tried to use BackgroundUploadAsync(it is for Silverlight apps) and it works on phone - uploads file and tracks progress right. But when I tried to upload big file(in my case > 150Mb) I noted that exactly after 120 seconds upload operation just resets to 0% and starts again without any exceptions.
Here is code for Windows & WP81 approach:
var progressHandler = new Progress<LiveOperationProgress>(
(progress) =>
{
var res = progress.ProgressPercentage;
});
LiveUploadOperation uploadOperation = await liveConnectClient.CreateBackgroundUploadAsync(uploadPath, "testfile.wav", file, OverwriteOption.Rename);
LiveOperationResult uploadResult = await uploadOperation.StartAsync(new CancellationToken(), progressHandler);
And for Silverlight:
var progressHandler = new Progress<LiveOperationProgress>(
(progress) =>
{
var res = progress.ProgressPercentage;
});
LiveOperationResult opResult = await connectClient.BackgroundUploadAsync(CurrentFolderId,
file.Name,
stream,
OverwriteOption.Rename,
record.GetCTS().Token,
progressHandler);
So question - how to make it upload files of any size, redefine timeout(currently 120s) and track progress on both Windows and WP81?
UPD:
I found the reason of 2 mins timeout here:
After the connection has been established, an HTTP request message that has not received a response within two minutes is aborted.
Is it normal for PUT request?

Related

System.Drawing.Image 'Parameter is not valid' when image source is from Android

I am developing a Blazor WASM app to interface with the backend of a winforms application. Images in this winforms application are loaded with System.Drawing.Image.FromStream().
Images that are uploaded from my web app are working correctly when done from my computer; but if I use my Android phone, then System.Drawing.Image gives me the Parameter is not valid exception when loading from the stream. Unfortunately, I don't have any other devices to attempt from. Both devices used Chrome browser.
I have dumped the stream to a file to ensure that the stream is not broken, which works as expected.
I have tried with validateImageData set to false
I have a small reproducible snippet using the System.Drawing.Common nuget package for asp core:
index.razor
<InputFile OnChange="#OnInputFileChange" />
#code {
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
var fileContent = new StreamContent(e.File.OpenReadStream());
using var content = new MultipartFormDataContent();
content.Add(
content: fileContent,
name: "\"files\"",
fileName: e.File.Name);
var response = await Http.PostAsync("/WeatherForecast/save", content);
}
}
Controller
[HttpPost("save")]
public async Task Save([FromForm] IEnumerable<IFormFile> files)
{
var file = files.First();
//throws exception if source comes from Android
Image img = Image.FromStream(file.OpenReadStream());
}
What is Android doing to the images to break System.Drawing.Image? What am I missing?
Edit:
After some more testing I have observed that there are other details that contribute to this exception being triggered. If the actual picture source is from somewhere say a download from Reddit, then the exception will occur, but if it is a picture taken from the phone itself it does not occur. Both images on my phone are being reported as a .jpg, but unfortunately, I just don't know enough about how images work under the hood to navigate my way through this problem.

Can one use Stream.Position to track upload progress without causing issues?

I'm using a MinIO S3 file server to store user data of my blazor server side application. Since users are working with datasets for some ML applications, quite a lot of files need to be updated.
Initial Issue
I'm stating my initial issue, just for completeness and to avoid creating a y/x problem post (However, I'm curious about my attempted solution in any case):
I'm using a hidden <InputFile/> and some javascript to create a drop area for the files the user wants to upload. Problem is that if more then ~200-250 files are dropped (i.e. OnChange event with those files is triggered), the blazor circuit breaks.
Attempted Solution
My solution was rather simple: Force the user to upload zipped files with the completed dataset, if the file count is >150.
New Problem
For long running upload operations I need some user feedback. For single files the upload is fast enough to have some GUI changes after each file, but the MinIO .NET client doesn't seem to have any way to know the progress of a single file upload.
Here is the current code for a single file upload:
public async Task StoreImage(ImageDatabaseModel image, Stream dataStream, string contentType, long fileSize)
{
await CreateBucketIfNotExists(image.UserID);
PutObjectArgs args = new PutObjectArgs()
.WithBucket(image.UserID)
.WithObject(GetMinioImageName(image))
.WithStreamData(dataStream)
.WithContentType(contentType)
.WithObjectSize(fileSize);
await _minio.PutObjectAsync(args);
}
My idea is was now to use the stream to get the progress information. Here is to code of an initial test:
public async Task StoreZibFile(ImageDatabaseModel image, Stream dataStream, string contentType, long fileSize)
{
// never mind I'm still uploading an image, this is only for testing anyway
await CreateBucketIfNotExists(image.UserID);
PutObjectArgs args = new PutObjectArgs()
.WithBucket(image.UserID)
.WithObject(GetMinioImageName(image))
.WithStreamData(dataStream)
.WithContentType(contentType)
.WithObjectSize(fileSize);
var t1 = _minio.PutObjectAsync(args);
var t2 = Task.Run(async () =>
{
while (dataStream.Position < fileSize)
{
Console.WriteLine(dataStream.Position);
await Task.Delay(500);
}
});
await Task.WhenAll(t1, t2);
}
This gives the expected output of the dataStream.Position value rising during the upload.
The question is: Is this approach suitable for my usecase? Are there any downsides I'm unaware of?

Windows Phone 8.1 MediaComposition - Audio Too Fast When Stitching Videos

I am having a problem when trying to concatenate multiple videos together. Whenever I combine 2 or more videos, the audio is played at double speed, while the video plays out normally.
Below is the code. Am I missing something?
I get the same results when testing but cloning a single video or selecting multiple videos.
I have compared to the code example here (I am not trimming).
public static IAsyncOperation<IStorageFile> ConcatenateVideoRT([ReadOnlyArray]IStorageFile[] videoFiles, IStorageFolder outputFolder, string outputfileName)
{
return Task.Run<IStorageFile>(async () =>
{
IStorageFile _OutputFile = await outputFolder.CreateFileAsync(outputfileName, CreationCollisionOption.GenerateUniqueName);
MediaComposition _MediaComposition = new MediaComposition();
foreach (IStorageFile _VideoFile in videoFiles)
{
MediaClip _MediaClip = await MediaClip.CreateFromFileAsync(_VideoFile);
_MediaComposition.Clips.Add(_MediaClip);
_MediaComposition.Clips.Add(_MediaClip.Clone());
}
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile);
if (_TranscodeFailureReason != TranscodeFailureReason.None)
{
throw new Exception("Video Concatenation Failed: " + _TranscodeFailureReason.ToString());
}
return _OutputFile;
}).AsAsyncOperation();
}
It looks like there are two issues. I have got this working by adding the following line:
MediaEncodingProfile _MediaEncodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Vga);
And changing the following line:
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile);
To:
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile, MediaTrimmingPreference.Fast, _MediaEncodingProfile);
The problem seems to be that RenderToFileAsync doesn't appear to work properly when using VideoEncodingQuality.HD720p or VideoEncodingQuality.HD1080p, both of these settings recreate the fast audio issue. Also, using VideoEncodingQuality.Auto seems to cause the encode to fail (although I think it is meant to use the default settings from the camera).
Additionally, I posted the problem on the Microsoft Partner Community Forums and their response was that encoding can fail on specific devices, e.g. in their tests video recorded on a Lumia 638 could not be encoded/concatenated even on other devices, but video from a HTC 8x, Lumia 920 and Lumia 930 could be encoded on all devices even the 638.
They suggested this was a device problem (firmware) not a Windows.Media.Editing API problem.

Cannot read JSON file - FileNotFoundException

I was following tutorial on this page http://channel9.msdn.com/Series/Windows-Phone-8-1-Development-for-Absolute-Beginners/Part-22-Storing-and-Retrieving-Serialized-Data because I want my app to store data in JSON file and then read it back. 2 things about the tutorial:
I press write button - works fine, then press read button and it also works, however, I close down win phone 8.1 emulator, open it again, press read button and I got the An exception of type 'System.IO.FileNotFoundException'exception! Why is that, I should have the file already on disk from previously running the app ? Or is does it get erased when I close down emulator ? Also I looked for the specified file on disk and cannot find it ! Any help ?
private const string JSONFILENAME = "data.json";
private async Task readJsonAsync()
{
string content = String.Empty;
var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(JSONFILENAME);
using (StreamReader reader = new StreamReader(myStream))
{
content = await reader.ReadToEndAsync();
}
resultTextBlock.Text = content;
}
private async Task writeJsonAsync()
{ // Notice that the write is ALMOST identical ... except for the serializer.
var myCars = buildObjectGraph();
var serializer = new DataContractJsonSerializer(typeof(List<Car>));
using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
JSONFILENAME,
CreationCollisionOption.ReplaceExisting))
{
serializer.WriteObject(stream, myCars);
}
resultTextBlock.Text = "Write succeeded";
}
When you close the Emulator its state is is not preserved, meaning that the apps that you tested are not there when you restart the emulator. Therefore, VS will make a new install when you open up the emulator again.
The same happens when you do a rebuild of your project. Then, VS will remove the app from the emulator and reinstall it from scratch. This in turn will also result in loosing your JSON file.
When you want to make sure that your data is preserved then don't close the emulator and just use Build from within VS (VS decides from time to time to rebuild your app though).
On order to test your app more properly I suggest you have a look at the Windows Phone Power Tools (http://wptools.codeplex.com/). There you can explicitly choose to install or update a given XAP package.

How to simply access SkyDrive, write and read files?

I want to use SkyDrive to backup some information.
But seems they have removed this namespace Microsoft.Live.Controls; from the new SDK, and all code samples and also answers here are outdated.
this reference also is outdated; there is no more LiveConnectClient
How can I simply backup files to SkyDrive after these changes?
(any code sample or reference is appreciated.)
It's not that hard, but there really are no references or tutorials. Everything that's below works just fine in my Windows Phone 8 project.
You need to include Microsoft.Live namespace after installing Live SDK.
First you have to create and initialize the client. After that, you log in and can send over some data:
LiveConnectClient client;
var auth = new LiveAuthClient("YourGeneratedKey");
var result = await auth.InitializeAsync(new [] {"wl.basic", "wl.signin", "wl.skydrive_update" });
// If you're not connected yet, that means you'll have to log in.
if(result.Status != LiveConnectSessionStatus.Connected)
{
// This will automatically show the login screen
result = await auth.LoginAsync(new [] {"wl.basic", "wl.signin", "wl.skydrive_update" });
}
if(result.Status == LiveConnectSessionStatus.Connected)
{
client = new LiveConnectClient(result.Session);
}
Maybe the process above could be simplified, but it works for me.
Now you can use the client if everything went as planned. I've managed to successfully upload files from streams.
Let's say you've obtained a Stream to the file you want to send (I got that via WinRT file API on Windows Phone 8, IStorageFolder, then getting the file, then file.OpenStreamForReadAsync()), I'll just assume it's a text file for example purposes:
using(stream)
{
await client.UploadAsync("me/skydrive", "myfile.txt", stream, OverwriteOption.Overwrite);
}
Actually, I've used the overload that also accepts CancellationToken and IProgress<LiveOperationProgress>, mostly for progress notifications.
There, that should upload the file to the main directory on logged user's SkyDrive.

Categories

Resources