I am having problem downloading files using Background transfer. After completion of download when moving file, it gives you an exception Operation not permitted
void addTransferRequest(string fileName)
{
if (string.IsNullOrEmpty(fileName))
return;
string filePathToDownload = string.Empty;
filePathToDownload = activeReciter.DownloadURL;
filePathToDownload += fileName;
Uri transferUri = new Uri(Uri.EscapeUriString(filePathToDownload),
UriKind.RelativeOrAbsolute);
BackgroundTransferRequest transferRequest = new
BackgroundTransferRequest(transferUri);
transferRequest.Method = "GET";
transferRequest.TransferPreferences = TransferPreferences.AllowBattery;
Uri downloadUri = new Uri(DataSource.TEMPDOWNLOADLOCATION + fileName,
UriKind.RelativeOrAbsolute);
transferRequest.DownloadLocation = downloadUri;
transferRequest.Tag = fileName;
transferRequest.TransferStatusChanged +=
new EventHandler<BackgroundTransferEventArgs>
(transfer_TransferStatusChanged);
transferRequest.TransferProgressChanged += new
EventHandler<BackgroundTransferEventArgs>(transfer_TransferProgressChanged);
try
{
BackgroundTransferService.Add(transferRequest);
chapterFileNames.Dequeue();
}
catch (InvalidOperationException)
{
}
catch (Exception)
{
}
}
void transfer_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
{
ProcessTransfer(e.Request);
}
void transfer_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
{
}
private void ProcessTransfer(BackgroundTransferRequest transfer)
{
switch (transfer.TransferStatus)
{
case TransferStatus.Completed:
if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
{
using (IsolatedStorageFile isoStore =
IsolatedStorageFile.GetUserStoreForApplication())
{
try
{
string filename = transfer.Tag;
string folderPath = string.Format(#"{0}{1}\{2}\",
DataSource.DOWNLOADLOCATION, activeReciter.ReciterID, chapter.ChapterID);
string fileFullPath = folderPath + filename;
if (!isoStore.DirectoryExists(Path.GetDirectoryName(folderPath)))
isoStore.CreateDirectory(Path.GetDirectoryName(folderPath));
if (isoStore.FileExists(fileFullPath))
isoStore.DeleteFile(fileFullPath);
isoStore.MoveFile(transfer.DownloadLocation.OriginalString, fileFullPath);
//Excpetion is thrown here
RemoveTransferRequest(transfer.RequestId);
}
catch (Exception ex)
{
MessageBox.Show("Error Occured: " + ex.Message + transfer.Tag, "Error",
MessageBoxButton.OK);
return;
}
}
}
break;
}
}
When moving file, it throws exception, I don't know what is wrong with moving (this happens on some of the files not all files).
From the MSDN Page, under File System Restrictions section:
You can create any additional directory structure you choose
underneath the root “/shared/transfers” directory, and you can copy or
move files after the transfer is complete to ensure that the
background transfer service does not modify the files, but attempting
to initiate a transfer using a path outside of the “/shared/transfers”
directory will throw an exception.
Make sure you are not trying to move your file outside from the /Shared/Transfers folder.
Related
This script generate a txt file in Download folder on Android device.
public class WriteCSVInDownloadFolder : MonoBehaviour
{
public TMP_Text Text;
private void Start()
{
try
{
var txtpath = GetDownloadFolder() + "/Test.txt";
FileStream file = new FileStream(txtpath, FileMode.Create, FileAccess.Write);
}
catch (IOException e)
{
Text.text = e.Message;
}
}
public static string GetDownloadFolder()
{
string[] temp = (Application.persistentDataPath.Replace("Android", "")).Split(new string[] { "//" }, System.StringSplitOptions.None);
return (temp[0] + "/Download");
}
}
But, when I manually remove this file and execute this script again, I receive an exception: "File already exists"
Therefore , I have tried to use FileMode.Truncate and File.Exists functions, however, I receive another exception: "Could not find file"
Any idea?
Update 1
I tried to solve the problem with Dispose() method, but the problem persist.
TextWriter writer = File.CreateText(path);
writer.Write("Hello World");
writer.Flush();
writer.Dispose();
Update 2
I tried to remove residual entries getting Uri, but not working.
Uri uri = new Uri(txtpath);
if (uri.IsFile)
{
string filename = Path.GetFileName(uri.LocalPath);
Text.text = filename;
File.Delete(uri.LocalPath);
}
Update 3
Current code
private void Awake()
{
try
{
txtpath = FileManager.GetFolder("/Download") + "/Test.txt";
if (File.Exists(txtpath))
{
Text.text = "Exist";
File.Delete(txtpath);
}
else
{
Text.text = "Not existe";
FileStream file = new FileStream(txtpath, FileMode.Create, FileAccess.Write);
}
}
catch (IOException e)
{
Text.text = e.Message;
}
}
Update 4
New: I tried to use Path.Combine.
Exception thrown: "Access to the path "..." is denied".
public class ReadCSVInDownloadFolder : MonoBehaviour
{
public TMP_Text Text;
private string path;
private void Awake()
{
try
{
path = Path.Combine("storage","emulated","0","Download", "Test.csv");
Text.text = File.ReadAllText(path);
}
catch (Exception e)
{
Text.text = e.Message;
}
}
}
While creating your file it has been indexed by the media store.
So there is an entry for the file in the media store.
There are a bunch of sloppy programmed file managers that delete the file but leave the entry.
So first delete that entry and then you go again.
I'm using FileSystemWatcher to detect directory changes, and after that I read file content and insert it to database.
Here's my code:
private FileSystemWatcher _watcher;
public MainWindow()
{
try
{
InitializeComponent();
GetFiles();
//Task.Factory.StartNew(() => GetFiles())
// .ContinueWith(task =>
// {
// }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
catch(Exception ex)
{
//..
}
}
public bool GetFiles()
{
_watcher = new FileSystemWatcher(Globals.iniFilesPath, "*.ini");
_watcher.Created += FileCreated;
_watcher.IncludeSubdirectories = false;
_watcher.EnableRaisingEvents = true;
return true;
}
private void FileCreated(object sender, FileSystemEventArgs e)
{
try
{
string fileName = Path.GetFileNameWithoutExtension(e.FullPath);
if (!String.IsNullOrEmpty(fileName))
{
string[] content = File.ReadAllLines(e.FullPath);
string[] newStringArray = content.Select(s => s.Substring(s.LastIndexOf('=') + 1)).ToArray();
ChargingStationFile csf = new Product
{
Quantity = Convert.ToDecimal(newStringArray[1]),
Amount = Convert.ToDecimal(newStringArray[2]),
Price = Convert.ToDecimal(newStringArray[3]),
FileName = fileName
};
ProductController.Instance.Save(csf);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
If I run this code with CTRL+F5 I received this message:
But If I go with F5 (Debugging mode) than I receive this and not this error about cannot access process and item is sucessfully saved. This is confusing me really..
Should I dispose watcher? or something like that? Maybe I'm missing something here?
This is first time I'm using FileSystemWatcher, obliviously something is really wrong here..
P.S I've found out that this line is causing an exception:
string[] content = File.ReadAllLines(e.FullPath);
how come?
Thanks guys
Cheers
File.ReadAllLines() cannot access the file when it is open for writing in another application but you can use a FileStream and StreamReader instead.
Replace string[] content = File.ReadAllLines(e.FullPath); with the following code and you should be able to read the contents of the file regardless of whether it is open in another application:
List<string> content = new List<string>();
using (FileStream stream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(stream))
{
while (!sr.EndOfStream)
content.Add(sr.ReadLine());
}
As mention in this answer:
Most likely what is happening here is that the FileCreated event is
being raised and tries to process the file before is has been
completely written to disk.
So, you need to wait until the file has finished to copy. According to this other answer:
From the documentation for FileSystemWatcher:
The OnCreated event is raised as soon as a file is created. If a file
is being copied or transferred into a watched directory, the OnCreated
event will be raised immediately, followed by one or more OnChanged
events.
So, a workaround for your case will be to create a list of strings containing the paths of the files that could not be read in the Created method handler, and re-process those paths in the Changed event of the FileSystemWatcher (read the comments in the code) :
public partial class MainWindow : Window {
private FileSystemWatcher _watcher;
public MainWindow() {
try {
InitializeComponent();
GetFiles();
} catch (Exception ex) {
MessageBox.Show($"Exception: {ex.Message}");
}
}
private bool GetFiles() {
_watcher = new FileSystemWatcher(#"C:\TestFolder", "*.ini");
_watcher.Created += FileCreated;
_watcher.Changed += FileChanged; // add this.
_watcher.IncludeSubdirectories = false;
_watcher.EnableRaisingEvents = true;
return true;
}
// this field is new, and contains the paths of the files that could not be read in the Created method handler.
private readonly IList<string> _waitingForClose = new List<string>();
private void FileChanged(object sender, FileSystemEventArgs e) {
if (_waitingForClose.Contains(e.FullPath)) {
try {
string[] content = File.ReadAllLines(e.FullPath);
string[] newStringArray = content.Select(s => s.Substring(s.LastIndexOf('=') + 1)).ToArray();
MessageBox.Show($"On FileChanged: {string.Join(" --- ", newStringArray)}");
// Again, process the data from the file to saving in the database.
// removing the path, so as not to reprocess the file..
_waitingForClose.Remove(e.FullPath);
} catch (Exception ex) {
MessageBox.Show($"Exception on FileChanged: {ex.Message} - {e.FullPath}");
}
}
}
private void FileCreated(object sender, FileSystemEventArgs e) {
try {
string fileName = Path.GetFileNameWithoutExtension(e.FullPath);
if (!String.IsNullOrEmpty(fileName)) {
string[] content = File.ReadAllLines(e.FullPath);
string[] newStringArray = content.Select(s => s.Substring(s.LastIndexOf('=') + 1)).ToArray();
MessageBox.Show($"On FileCreated: {string.Join(" --- ", newStringArray)}");
// process the data from the file to saving in the database.
}
} catch (Exception ex) {
// if the method fails, add the path to the _waitingForClose variable
_waitingForClose.Add(e.FullPath);
//MessageBox.Show($"Exception on FIleCreated: {ex.Message} - {e.FullPath}");
}
}
}
I use BackgroundTransferRequest class to download mp3 files in my wp8 app. Some of my files are over 100mb, so because of that I set transferRequest.TransferPreferences = TransferPreferences.None;. However, transferstatus method still returns me external power message.
If you look at line 12 in code you can see that i set TransferPreferences as None
Here is my code to download mp3 file:
private void download_Tap_1(object sender, System.Windows.Input.GestureEventArgs e)
{
if (transferFileName != null)
{
Uri transferUri = new Uri(Uri.EscapeUriString(transferFileName), UriKind.RelativeOrAbsolute);
BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
transferRequest.Method = "GET";
string downloadFile = transferFileName.Substring(transferFileName.LastIndexOf("/") + 1);
Uri downloadUri = new Uri("shared/transfers/" + downloadFile, UriKind.RelativeOrAbsolute);
transferRequest.DownloadLocation = downloadUri;
transferRequest.Tag = downloadFile;
transferRequest.TransferPreferences = TransferPreferences.None;
try
{
BackgroundTransferService.Add(transferRequest);
}
catch (InvalidOperationException ex)
{
// TBD - update when exceptions are finalized
MessageBox.Show("Unable to add background transfer request. " + ex.Message);
}
catch (Exception e2)
{
MessageBox.Show("Unable to add background transfer request."+e2.ToString());
}
transferRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged);
transferRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferProgressChanged);
}
else
MessageBox.Show("select an mp3 file to download");
}
private void ProcessTransfer(BackgroundTransferRequest transfer)
{
switch (transfer.TransferStatus)
{
case TransferStatus.Completed:
if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
{
RemoveTransferRequest(transfer.RequestId);
processresult.Text = "";
download.Visibility = Visibility.Visible;
lnk = new linkname();
URLListBox.ItemsSource = lnk.obj();
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
string filename = transfer.Tag;
if (isoStore.FileExists(filename))
{
isoStore.DeleteFile(filename);
}
isoStore.MoveFile(transfer.DownloadLocation.OriginalString, filename);
}
}
else
{
RemoveTransferRequest(transfer.RequestId);
if (transfer.TransferError != null)
{
MessageBox.Show(transfer.TransferError.ToString());
}
}
break;
case TransferStatus.WaitingForExternalPower:
WaitingForExternalPower = true;
processresult.Text = "Waiting For External Power";
break;
case TransferStatus.WaitingForExternalPowerDueToBatterySaverMode:
WaitingForExternalPowerDueToBatterySaverMode = true;
processresult.Text = "Waiting For External Power Due To Battery Saver Mode";
break;
case TransferStatus.WaitingForNonVoiceBlockingNetwork:
WaitingForNonVoiceBlockingNetwork = true;
processresult.Text = "Waiting For Non Voice Blocking Network";
break;
case TransferStatus.WaitingForWiFi:
WaitingForWiFi = true;
processresult.Text = "Waiting For WiFi";
break;
}
}
private void transfer_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
{
ProcessTransfer(e.Request);
}
From the Documentation
If the file to be transferred is larger than 100 MB, set the TransferPreferences property of the transfer to None. If you do not, the system will automatically change the transfer settings to this value, meaning that the transfer will only proceed when the phone is connected to external power and has a Wi-Fi connection.
I have a form with a File Watcher to which he transfers to multiple addresses all video files placed in a folder. What is the best option so that when multiple files are added to even be able to perform each transfer in a thread. Here's an example of my code:
DockingBarTransferEntities context = new DockingBarTransferEntities();
private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
{
IEnumerable<Diretorios> directories = context.Diretorios.ToList();
foreach (var destino in directories)
{
try
{
Transfere(e.FullPath,Path.GetFileName(e.FullPath),destino);
}
catch (Exception ex)
{
textBox1.Text += "Error: " + ex.Message;
}
}
}
public void Transfere(string fullPath, string name, Diretorios diretorio)
{
try
{
if (Directory.Exists(diretorio.Caminho))
{
string fileName = Path.GetFileName(fullPath);
fileName = String.Format("{0}\\{1}", diretorio.Caminho, fileName);
FileInfo arquivo = new FileInfo(fullPath);
arquivo.CopyTo(fileName, true);
}
}
catch (Exception ex)
{
}
}
It should be as simple as this:
Task.Factory.StartNew(() => Transfere(e.FullPath, Path.GetFileName(e.FullPath), destino));
instead of calling Transfere directly.
When I try to open a .txt file it only shows its location in my textbox.
I am out of ideas:( hope you can help me...
code:
private void OpenItem_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
System.IO.StringReader OpenFile = new System.IO.StringReader(openFileDialog1.FileName);
richTextBox1.Text = OpenFile.ReadToEnd();
OpenFile.Close();
}
A StringReader reads the characters from the string you pass to it -- in this case, the file's name. If you want to read the contents of the file, use a StreamReader:
var OpenFile = new System.IO.StreamReader(openFileDialog1.FileName);
richTextBox1.Text = OpenFile.ReadToEnd();
Use File.ReadAllText
richTextBox1.Text = File.ReadAllText(openFileDialog1.FileName);
I'd use the File.OpenText() method for reading text-files. You should also use using statements to properly dispose the object.
if(openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
// Make sure a file was selected
if ((myStream = openFileDialog1.OpenFile()) != null) {
// Open stream
using (StreamReader sr = File.OpenText(openFileDialog1.FileName))
{
// Read the text
richTextBox1.Text = sr.ReadToEnd();
}
}
}
catch (Exception ex)
{
MessageBox.Show("An error occured: " + ex.Message);
}
}
That's easy. This is what you need to do:
1) Put using System.IO; above namespace.
2) Create a new method:
public static void read()
{
StreamReader readme = null;
try
{
readme = File.OpenText(#"C:\path\to\your\.txt\file.txt");
Console.WriteLine(readme.ReadToEnd());
}
// will return an invalid file name error
catch (FileNotFoundException errorMsg)
{
Console.WriteLine("Error, " + errorMsg.Message);
}
// will return an invalid path error
catch (Exception errorMsg)
{
Console.WriteLine("Error, " + errorMsg.Message);
}
finally
{
if (readme != null)
{
readme.Close();
}
}
}
3) Call it in your main method: read();
4) You're done!