PCLStorage/ZipArchive Difference between debug and release - zip

Hello all you clever folks in this great city called stackoverflow.
I come to you with a problem i can't seem to figure out.
My issue is that i am developing an app using xamarin forms in vs2015.
In this app i download some zipped data (image/audio) from a webservice and saves it to my phone with the nuget PCLStorage and (when needed) unzips a file to display/play.
The app works fine when using "Debug" mode but when i package the app as apk and install it on my phone, i throws "Object reference not set to an instance of an object" when i try to open the zip file with ziparchive
The CheckExistsaAsync tells me the file exists, and the await DisplayAlert tells me the length of the stream is the same as when the file is saved. It is also the same length as the file when running in debug mode.
Here is the code that fails on me:
IFolder rootFolder = FileSystem.Current.LocalStorage;
if(await rootFolder.CheckExistsAsync("SavedData.zip") == ExistenceCheckResult.FileExists)
{
IFile file = await rootFolder.GetFileAsync("SavedData.zip");
using(Stream s = await file.OpenAsync(FileAccess.Read))
{
await DisplayAlert("blabla", s.Length.ToString(), "ok");
using(ZipArchive zip = new ZipArchive(s, ZipArchiveMode.Read, false))
{
//Code
}
}
}
The line that failes on me is the using(ZipArchive zip = .....) line throwing the exception

It's quite hard to say but I am going to speculate File Permission Issue. Where does it download the file and does the Android App have the appropriate permissions to access that file location.

ALAS! i have found a solution!
https://forums.xamarin.com/discussion/45701/system-io-compression-zipfile-extracttodirectory-fails-in-release-mode

Related

AddApacheModRewrite method suggesting that file doesn't exist (when it does)

Just trying to put an ApacheModRewrite call in my .NET Core 3.1 web application, and no matter what I do, it keeps telling me that the file does not exist. I've verified that the file exists at that location, I've tried creating a custom PhysicalFileProvider, and I've tried to set the file as Content/Copy Always, but no matter what I do, I cannot get past this code:
var options = new RewriteOptions()
.AddApacheModRewrite(env.ContentRootFileProvider, env.ContentRootPath + ".htaccess");
And the error:
System.IO.FileNotFoundException: 'The file F:\Source\MyWebsite\htaccess.txt does not exist.'
Where env.ContentRootFileProvider resolves to path: "F:\Source\MyWebsite" and again I have confirmed that the .htaccess file does, indeed, exist. I've also tried a variety of different ways to access the file path in the AddApacheModRewrite, but I'm really scratching my head on this one.
What am I doing wrong?
Figured it out. I had to use a streamreader, read the file, and then was able to apply it:
using (StreamReader apacheModRewriteStreamReader
File.OpenText(env.ContentRootPath + "\\.htaccess"))
{
var options = new RewriteOptions()
.AddApacheModRewrite(apacheModRewriteStreamReader);
app.UseRewriter(options);
}

play a downloaded mp3 in xamarin forms

I am able to play a file "test.mp3" added as a resource into the "Resources\Sounds\" folder of my pcl project by calling
AudioManager.Audio.Manager.PlaySound("test.mp3");
Now I am trying to play an audio file that I have downloaded from my webapi service. I am using the RestSharp library to download the file and the PCLStorage library to store the file:
try
{
var fileId = new Guid("test2");
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder resources = await rootFolder.CreateFolderAsync("Resources", CreationCollisionOption.OpenIfExists);
IFolder soundsFolder = await rootFolder.CreateFolderAsync("Sounds", CreationCollisionOption.OpenIfExists);
IFile myFile = await soundsFolder.CreateFileAsync($"{fileId}.mp3", CreationCollisionOption.ReplaceExisting);
using (var stream = await myFile.OpenAsync(fileAccess: FileAccess.ReadAndWrite))
{
var request = new RestRequest($"{fileId}");
var client = new RestClient();
client.BaseUrl = new System.Uri("http://10.0.2.2/MyApp.WebApi/api/");
var bytes = client.DownloadData(request);
foreach (var myByte in bytes)
{
stream.WriteByte(myByte);
}
}
}
catch (Exception e)
{
}
I also tried saving the file to the root dir but this also doesn't work.
The file seems to download just fine as far as I can tell (no errors). But I have yet to find a way to verify this by locating the file on the android emulator. I guess I first need to install the play store somehow and then download ES File explorer to see the file structure on the android emulator.
The problem is that when I try to play the soundfile in the same way I did with the embedded resource it won't work.
AudioManager.Audio.Manager.PlaySound("test2.mp3");
I guess this is because of the magic that happens during compile time to migrate the embedded resources to "somewhere" on the android emulator.
My main problem is that I do not understand what path to use to
write the file (tried resources/sounds and root)
read the file (tried
resources/sounds and root)
in order to be able to play the file
It turns out the AudioManager library assumes sounds are always Assets.
In it's NewSound method in the android code it tries to build an AssetFileDescriptor by using the following line:
Forms.Context.Assets.OpenFd(filePath);
I guess this method wants a filepath relative to the assets folder (for compiled resources) and throws a FileNotFoundException otherwise. This exception, however thrown, did not reach my catch statement in my pcl code. (it looks like it get's swallowed somewhere in the android -> pcl layer??)
Now I am using the SoundPool.LoadAsync with a filepath rather than a AssetFileDescriptor and this fixes my problem.
Yay!

Unable to open local file using cordova inappbrowser on windows 8.1 platform

I am developing a phone gap application and we've recently added support for the windows 8.1 platform. The application downloads/creates files which are saved to the device using the Cordova FileSystem API.
I have successfully saved a file to the device using a URL which looks like this
ms-appdata:///local/file.png
I have checked on my PC and the file is viewable inside the LocalState folder under the app's root folder. However, when I try to open this file using inAppBrowser nothing happens; no error message is being reported and none of the inAppBrowser default events fire.
function empty() { alert('here'); } //never fires
var absoluteUrl = "ms-appdata:///local/file.png";
cordova.InAppBrowser.open(absoluteURL, "_blank", "location=no", { loadstart: empty, loadstop: empty, loaderror: empty });
I have verified that the url is valid by calling the following built-in javascript on the url
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).done(function (file) {
debugger; //the file object contains the correct path to the file; C:\...etc.
});
Also, adding the url as the src for an img tag works as expected.
I have also tried attaching the inAppBrowser handlers using addEventListener("loadstart") etc. but none of them are firing either. However, when I try to open "http://www.google.com" the events do fire and the inAppBrowser pops up on the screen.
After inspecting the dom I can see that the inAppBrowser element has been added, but it doesn't appear to have a source attribute set
<div class="inAppBrowserWrap">
<x-ms-webview style="border-width: 0px; width: 100%; height: 100%;"></x-ms-webview>
</div>
I have looked at other questions such as this one but to no avail. I have verified that
a) InAppBrowser is installed
b) deviceReady has fired
I have also tried changing the target to "_self" (same issue) and "_system" (popup saying you need a new app to open a file of type msappdata://) and I'm running out of ideas. Has anybody come across similar issues?
I had a similar problem. My cordova app downloads a file and then opens it with native browser (so that images, PDF files and so on are properly handled).
In the end I had to modify InAppBrowserProxy.js class (part of InAppBrowser plugin for Windows platform).
This is the code that opens the file (plain JavaScript):
// This value comes from somewhere, I write it here as an example
var path = 'ms-appdata:///local//myfile.jpg';
// Open file in InAppBrowser
window.open(path, '_system', 'location=no');
Then, I updated InAppBrowserProxy.js file (under platforms\windows\www\plugins\cordova-plugin-inappbrowser\src\windows). I replaced this code fragment:
if (target === "_system") {
url = new Windows.Foundation.Uri(strUrl);
Windows.System.Launcher.launchUriAsync(url);
}
By this:
if (target === "_system") {
if (strUrl.indexOf('ms-appdata:///local//') == 0) {
var fileName = decodeURI(strUrl.substr(String(strUrl).lastIndexOf("/") + 1));
var localFolder = Windows.Storage.ApplicationData.current.localFolder;
localFolder.getFileAsync(fileName).then(function (file) {
Windows.System.Launcher.launchFileAsync(file);
}, function (error) {
console.log("Error getting file '" + fileName + "': " + error);
});
} else {
url = new Windows.Foundation.Uri(strUrl);
Windows.System.Launcher.launchUriAsync(url);
}
}
This is a very ad-hoc hack, but it did the trick for me, and it could be improved, extended, and even standarized.
Anyway, there may be other ways to achieve this, it's just that this worked for me...
After more searching, it seems that the x-ms-webview, which is the underlying component used by PhoneGap for Windows only supports loading HTML content. This Microsoft blog post on the web view control states that
UnviewableContentIdentified – Is fired when a user navigates to
content other than a webpage. The WebView control is only capable of
displaying HTML content. It doesn’t support displaying standalone
images, downloading files, viewing Office documents, etc. This event
is fired so the app can decide how to handle the situation.
This article suggests looking at the Windows.Data.Pdf namespace for providing in-app support for reading PDFs.

Epplus xlsx file won't open in libreoffice after downloading, but will open in excel

I'm generating an EEPlus .xlsx file that the user can download after clicking a button. It won't open on my Win8 machine with LibreOffice 4.4.1.2, but it will open on my coworkers Win8 machine using Excel 2013.
I get an error saying the file is corrupt and needs to be repaired, and when I try to repair it, it says it's unable to. My coworker also gets this error but is able to repair it and view the file.
Here's the relevant code for the creation of the downloadable version:
MemoryStream ms = DataTableToExcelXlsx(dt, "Report");
ms.Position = 0;
ms.WriteTo(Response.OutputStream);
Response.ContentType="application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment;filename=DataTable.xlsx");
Response.StatusCode = 200;
Now the weird part is that I'm also generating an xlsx file that is attached to an email, and it opens just fine. Neither me nor my coworker receive the error when opening the file attached to to the email.
Relevant code for the creation of the email attached version:
MemoryStream ms = DataTableToExcelXlsx(dtReportData, sReportTitle);
ms.Position = 0;
MailMessage mail = new MailMessage("you#yourcompany.com", sReportEmails);
using (SmtpClient client = new SmtpClient())
{
mail.Subject = "Mixer - Test Scheduler Task Execute.";
mail.Body = string.Format("The following report is executing. ReportSettings Id: {0}", reportSettingsId);
mail.Attachments.Add(new Attachment(ms, sReportTitle + ".xlsx", "application/vnd.ms-excel"));
client.Send(mail);
}
I've also tried using the vnd.ms-excel MIME type for the downloadable version and that didn't work, so I'm at a loss as to why this is happening.
I would have liked to answer this as a comment, but no reputation yet, or whatsoever.
Firstly, Why dont you try to use this content type?
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Currently, it does seem to be wrong. Please see as well this post, in which correct mime types are defined.
Try making a unit test or command line app that creates the xlsx to your local hard drive (avoiding all the the web Response stuff). Then see if the error shows up in that xlsx.
If it does then it is the code that create the file. Post it up and we can take a look.
If it does not then something is up with the response settings. Maybe in the disposition? Here I have an Response stream that I know works: Open ExcelPackage Object with Excel application without saving it on local file path

How to get the file path and file name of image captured from firefox camera in Firefox OS (ZTE device)

I am using Web activity to launch default Firefox camera from my web app in Firefox OS. Able to launch default Firefox camera and took picture. Got this.result as return value inside pick success.
Now I need to get file path, where image get saved and also image file name.
Tried to parse the this.result.blob, but couldn't find the path or file related parameter .
Below is the code I'm using
var activity = new MozActivity({
// Ask for the "pick" activity
name: "pick",
// Provide the data required by the filters of the activity
data: {
type: "image/jpeg"
}
});
activity.onsuccess = function() {
var picture = this.result;
console.log("A picture has been retrieved");
};
The image file name is not returned, as you can see from the code. If you would need the file name (I can't really think of a very good use case to be honest) you can iterate over the pictures storage in the DeviceStorageAPI and get the last saved file. It's probably the one from the camera (compare blobs to be totally sure).
In your success handler, you will get the file name if you use:
this.result.blob.name
And, you can get the path to the file as:
window.URL.createObjectURL(this.result.blob);
Source

Resources