I've a UWP app that downloads a pdf file from a website to ApplicationData.Current.LocalFolder, but when I use the Explorer to open the downloaded file, its size is always 0KB and it can't be opened.
For downloading, I used following code:
using System.Diagnostics;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
private async void Button_Click(object sender, RoutedEventArgs e)
{
try
{
Uri source = new Uri("http://www.sachsen.schule/~goethe-gym-auerbach/vplan/VertretungsplanMo.pdf");
StorageFile destinationFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("VertretungsplanMo.pdf", CreationCollisionOption.ReplaceExisting);
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadOperation download = downloader.CreateDownload(source, destinationFile);
Debug.WriteLine("Download successfull");
}
catch (Exception ex)
{
Debug.WriteLine("Download error. Exception: " + ex);
}
}
Although I never get a download error, the file is always 0 KB.
you are forgetting to call download.StartAsync()
Beside that the BackgroundDownload api's are very powerful because it will make sure the files are downloaded also when the app is not running. But they are not that easy neither. So i recommend to use just the HttpClient for simplicity or check some samples with the backgrounddownloader.
See https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BackgroundTransfer for more samples around background tranfser
Related
I'm creating an UWP application to split CSV and Excel files. The user has to select a file in any folder on the machine and the application has to read the file. At the end of the process, the application has to save one or more files based on what the user wants.
When I try to read a CSV file with this code
using (var reader = new StreamReader(file))
using (var csv = new CsvReader(reader, config))
{
return csv.GetRecords<dynamic>();
}
I receive an error
System.UnauthorizedAccessException: 'Access to the path 'C:\Users\enric\Downloads\combined_data.csv' is denied.'
I checked the capabilities in the Package.appxmanifest but there is none related to files or folders. There is only Removable Storage that seems similar to what I'm looking for but it doesn't work.
In the Microsoft documentation, I read to add a custom capability
<Capabilities><uap:Capability Name="documentsLibrary"/></Capabilities>
but it doesn't work either.
You don't need to specify capabilities, just use pick file or read file code, this code can be also found in Microsoft doc and doc.
private async void Btn_OpenFile_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
try
{
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".csv");
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
var file = await picker.PickSingleFileAsync();
if (file != null)
{
}
}
catch
{
}
}
When I call the following function, it should create a .txt file and write a sentence in it. It seems to execute without any errors. But I cannot find where this file is stored/located after being created. I ran a Windows Search to look for the file but nothing came up. Where is this file located? Also, what is the best folder/location to put a .txt file that the program uses? Should I put it in Solution Explorer of Visual Studio or Debug folder?
private async void CreateFile() {
try {
// Create sample file, replace if exists.
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile sampleFile = await storageFolder.CreateFileAsync("sample.txt", CreationCollisionOption.ReplaceExisting);
sampleFile = await storageFolder.GetFileAsync("sample.txt");
await FileIO.WriteTextAsync(sampleFile, "Swift as a shadow!");
} catch (Exception ex) {
textBox.Text = ex.ToString();
}
}
You can have the code show the path:
sampleFile = await storageFolder.GetFileAsync("sample.txt");
await new MessageDialog(sampleFile.Path).ShowAsync();
On Windows 10, this will be a path like:
C:\Users\[username]\AppData\Local\Packages\[Package family name]\LocalState\sample.txt
where username is the name of the logged on user and package family name is the package family name of your application
I'm trying to add multiple files to an already created ZIP file using PickMultipleFilesAsync(). I previously created the ZIP file I want to access in the same code using FilesavePicker.PickSaveFileAsync() method. The app is running on Windows 10 Pro version 1803 in Laptop PC, and I used Visual Studio Community 2017 to create it.
The problem I get is that, after following steps described in the FileOpenPicker MSDN page, I get a System.UnauthorizedAccessException: 'Access to the path 'C:\Users\'User'\Downloads{ZIP file}' is denied.'
I created ZIP file and tried to add new files using this code:
StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
// Prevent updates to the remote version of the file until we finish making changes and call CompleteUpdatesAsync.
CachedFileManager.DeferUpdates(file);
try
{
Stream stream = await file.OpenStreamForWriteAsync();
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Update))
{
// This line works fine, file is added
archive.CreateEntryFromFile(path_to_another_file, file_name_in_ZIP);
//....
var dialog = new MessageDialog("Do you want to add more files to ZIP?");
//... (dialog configuration for Yes/No options)
var result = await dialog.ShowAsync();
if(result.Label == "Yes")
{
Debug.WriteLine("Yes option was selected!");
// Include additional files
var openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add("*");
openPicker.SuggestedStartLocation = PickerLocationId.Downloads;
IReadOnlyList<StorageFile> addedFiles = await openPicker.PickMultipleFilesAsync();
if (addedFiles.Count > 0)
{
// Application now has read/write access to the picked file(s)
foreach (StorageFile addedFile in addedFiles)
{
Debug.WriteLine(addedFile.Path); // No problem here
// I get the UnauthorizedAccessException here:
archive.CreateEntryFromFile(addedFile.Path, #"additional files/" + addedFile.Name);
}
}
else
{
// Update log file
globalLog += GetTime() + "No additional files";
}
}
}
}
}
I already added <rescap:Capability Name="broadFileSystemAccess"/> to appxmanifest just in case, but as I had access to selected files using FileOpenPicker I think that is not the problem.
As I created the ZIP file within this code I should still have access to it, right? I suspect that FileOpenPicker somehow "closes" access to ZIP file in order to give access to files to be added, or that MessageDialog prevents of accessing the ZIP file I created after I called showAsync().
Is there any other way to achieve what I'm trying?
EDIT: I can not access the file(s) I select using FileOpenPicker, despite I can show file name(s) in Debug console. ZIP file access is OK.
I just found a solution. As stated here, you can use a buffer to stream file contents to ZIP file, just replace:
// I get the UnauthorizedAccessException here:
archive.CreateEntryFromFile(addedFile.Path, #"additional files/" + addedFile.Name);
With:
ZipArchiveEntry readmeEntry = archive.CreateEntry(#"additional files/" + addedFile.Name);
byte[] buffer = WindowsRuntimeBufferExtensions.ToArray(await FileIO.ReadBufferAsync(addedFile));
using (Stream entryStream = readmeEntry.Open())
{
await entryStream.WriteAsync(buffer, 0, buffer.Length);
}
That way, files are added and no UnauthorizedAccessException happens. Hope this helps anyone with the same problem!
Hello in my app I download ".mp3" file into isolated storage and user should be able to listen this ".mp3" file but it seems i cant reach ".mp3" file in play click event
here is my code
private IsolatedStorageFile isoStore;
public mp3kuran()
{
InitializeComponent();
using ( isoStore= IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isoStore.DirectoryExists("/shared/transfers"))
{
isoStore.CreateDirectory("/shared/transfers");
}
}
}
string link= "https://dl.dropboxusercontent.com/u/75638865/001.mp3";
private BackgroundTransferRequest transferRequest;
here is my download button action it downloads the mp3 file
private void download_Click(object sender, RoutedEventArgs e)
{
Uri transferuri = new Uri(Uri.EscapeUriString(link), UriKind.RelativeOrAbsolute);
// Create the new transfer request, passing in the URI of the file to
// be transferred.
transferRequest = new BackgroundTransferRequest(transferuri);
// Set the transfer method. GET and POST are supported.
transferRequest.Method = "GET";
string downloadFile = link.Substring(link.LastIndexOf("/") + 1);
Uri downloadUri = new Uri("shared/transfers/" + downloadFile, UriKind.RelativeOrAbsolute);
transferRequest.DownloadLocation = downloadUri;
transferRequest.Tag = downloadFile;
// Add the transfer request using the BackgroundTransferService. Do this in
// a try block in case an exception is thrown.
try
{
BackgroundTransferService.Add(transferRequest);
}
catch (InvalidOperationException ex)
{
MessageBox.Show("Unable to add background transfer request. " + ex.Message);
}
catch (Exception)
{
MessageBox.Show("Unable to add background transfer request.");
}
}
here play button click event
private void play_Click(object sender, RoutedEventArgs e)
{
string fileName = transferRequest.Tag;
MessageBox.Show(fileName);
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isoStore.FileExists(fileName))
{MessageBox.Show("here");
using (var isoStream = isoStore.OpenFile(fileName, FileMode.Open, FileAccess.Read))
{
mediaSound.Stop();
mediaSound.SetSource(isoStream);
mediaSound.Position = System.TimeSpan.FromSeconds(0);
mediaSound.Volume = 20;
mediaSound.Play();
}
}
}
}
in play_clic event i try to reach mp3 from isolated storage but i couldnt solve what is wrong because when I click button ,it does nothing
Some ideas...
Are you checking the BackgroundTransferRequest has completed before allowing the play button to be clicked?
Are you sure the complete file has been successfully downloaded by checking for the presence of a physical file, the same size as the original? You can use a tool like Windows Phone Toolkit to check this.
It does the Tag property on your BackgroundTransferRequest maintain the correct value after the download is complete?
Normally you'd check the status of the BackgroundTransferRequest and copy the file out of "/shared/transfers" to your own location. You'd then play the file from that location.
I have build an app with a webbrowser in it. It's working fine but when I try to navigate to an adress like bla.pdf the webbrowser shows nothing.
I solved this problem with automatically open the Internet Explorer if the adress is linking to a pdf file.
Is there a better solution? I want to open that PDF file in my own app and I dont want to open the Internet Explorer everytime. Any suggestions?
If you've got a locally downloaded PDF that is in Isolated Storage you can launch the PDF Reader application (or any other applications registered to open PDF files) using LaunchFileAsync.
private async void LaunchFileButton_Click(object sender, RoutedEventArgs rea)
{
// Access isolated storage.
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
// Access the PDF.
StorageFile pdfFile = await local.GetFileAsync("file1.pdf");
// Launch the bug query file.
Windows.System.Launcher.LaunchFileAsync(pdfFile);
}
(adapted from MSDN, see section on "launching a file").
If it's a remote URL then you can use LaunchUriAsync (which will use IE to download the file first).
You will need to try this on a device with the PDF Reader application installed - it won't work on the Emulator.
You should read following article if you are not familiar with Async: MSDN Asynchronous Programming with Async and Await
I couldn't test my app because my WP8 Phone is currently not available and I can't install an PDF reader on the emulator.
Call following method to start the download
WebClient pdfDownloader = null;
string LastFileName = ""; //To save the filename of the last created pdf
private void StartPDFDownload(string URL)
{
pdfDownloader = new WebClient(); //prevents that the OpenReadCompleted-Event is called multiple times
pdfDownloader.OpenReadCompleted += DownloadPDF; //Create an event handler
pdfDownloader.OpenReadAsync(new Uri(URL)); //Start to read the website
}
async void DownloadPDF(object sender, OpenReadCompletedEventArgs e)
{
byte[] buffer = new byte[e.Result.Length]; //Gets the byte length of the pdf file
await e.Result.ReadAsync(buffer, 0, buffer.Length); //Waits until the rad is completed (Async doesn't block the GUI Thread)
using (IsolatedStorageFile ISFile = IsolatedStorageFile.GetUserStoreForApplication())
{
try
{
LastFileName = "tempPDF" + DateTime.Now.Ticks + ".pdf";
using (IsolatedStorageFileStream ISFileStream = ISFile.CreateFile(LastFileName))
{
await ISFileStream.WriteAsync(buffer, 0, buffer.Length);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + Environment.NewLine + ex.HResult,
ex.Source, MessageBoxButton.OK);
//Catch errors regarding the creation of file
}
}
OpenPDFFile();
}
private async void OpenPDFFile()
{
StorageFolder ISFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
try
{
IStorageFile ISFile = await ISFolder.GetFileAsync(LastFileName);
await Windows.System.Launcher.LaunchFileAsync(ISFile);
//http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206987%28v=vs.105%29.aspx
}
catch (Exception ex)
{
//Catch unknown errors while getting the file
//or opening the app to display it
}
}
To call these methods from your WebBrowser-Control you need to catch the navigating event.
YourWebBrowserControl.Navigating += YourWebBrowserControl_Navigating;
void YourWebBrowserControl_Navigating(object sender, NavigatingEventArgs e)
{
if(e.Uri.AbsolutPath.EndsWith("pdf"))
{
StartPDFDownload(e.Uri.ToString());
}
}
Don't forget that you'll have to delete the files created someday.
Try this to open a PDF from a WebControl:
void MyWebBrowserControl_Navigating(object sender, NavigatingEventArgs e)
{
if (e.Uri.AbsolutPath.ToLower().EndsWith(".pdf"))
{
var success = Windows.System.Launcher.LaunchUriAsync(e.Uri);
}
}