I'm getting an error when clicking a button on a page to export data from a DataTable to a CSV file:
ERR_HTTP2_PROTOCOL_ERROR
This error only occurs on the published build. Everything works fine on my local machine in the development environment. It's published to a local machine on the network and then communicates directly with that, rather than over the internet (everything is local and on site, I should say). My assumption is threading being the issue, but I'm not sure how else to display dialog to the user and allow them to specify a path AND filename without SaveFileDialog.
protected void btnExportToCSV_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
try
{
int count = 1;
int totalColumns = dataTable.Columns.Count;
List<string> columnNames = new List<string>();
// add the column names/headers
foreach (DataColumn dr in dataTable.Columns)
{
columnNames.Add(dr.ColumnName);
sb.Append(dr.ColumnName);
if (count != totalColumns)
{
sb.Append(",");
}
count++;
}
sb.AppendLine();
string value = String.Empty;
// add the values for each row in corresponding column
foreach (DataRow dr in dataTable.Rows)
{
for (int x = 0; x < totalColumns; x++)
{
value = dr[x].ToString();
// filter out commas, line breaks, new lines and tabs
if (value.Contains(",") || value.Contains("\"") || value.Contains("<br />") || value.Contains("\t"))
{
value = '"' + value.Replace("\"", "\"\"") + '"';
}
// check that if current column is serial number,
// concat a character string to force it to display as a string
if (columnNames[x] == "SerialNum")
{
value = value.Insert(0, "#");
}
sb.Append(value);
// if not at the final column of a row, go to new column and NOT a new row
if (x != (totalColumns - 1))
{
sb.Append(",");
}
}
sb.AppendLine();
}
}
catch (Exception ex)
{
lblVerify.Text = "There was an issue building the CSV file data; please report the following message to xxxxxxx: " + ex.Message;
lblVerify.ForeColor = System.Drawing.Color.Red;
}
Stream myStream;
// build save dialog window with options
SaveFileDialog saveFileDialog1 = new SaveFileDialog
{
DefaultExt = "txt",
Title = "Save Reports",
Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*",
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
RestoreDirectory = true,
};
try
{
// separate thread to open and run save file browser
Thread thread = new Thread(() =>
{
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
// make sure the filename field is not blank
if ((myStream = saveFileDialog1.OpenFile()) != null)
{
myStream.Close();
// write the csv file to disk using the given file name
File.WriteAllText(saveFileDialog1.FileName.ToString(), sb.ToString());
}
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
catch(Exception ee)
{
lblVerify.Text = "There was an issue exporting the data to a CSV file; please report the following message to xxxxxxx: " + ee.Message;
lblVerify.ForeColor = System.Drawing.Color.Red;
}
}
I've been trying to figure out how to use the SaveFileDialog function in c# to save more than one file at a time.
The basic idea is, after the user has set parameters for a .cfg file, the user types out a set of serial numbers for which to save the configuration as. Then a SaveFileDialog is called allowing the user to save the one .cfg file under the names of the serial numbers the user listed.
Is this possible to do? Do you need to put the function into a loop, or is there another way to achieve this goal?
the .cfg file is set up like:
timezone=1
auto_DST=1
location=0
alarm_time=21
alarm_seconds_P=0
etc.
Here is what I have so far for saving that file:
List<Parameter> _paramList = new List<Parameter>();
List<Information> _infoList = new List<Information>();
saveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
saveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
saveFileDialog1.DefaultExt = ".CFG";
saveFileDialog1.FileName = ( "config_" + txtParamValue.Text);
saveFileDialog1.Filter = "Configuration files (*.CFG)|*.CFG|All files (*.*)|*.*";
if ( saveFileDialog1.ShowDialog( ) == DialogResult.OK )
{
using ( StreamWriter objWriter = new StreamWriter( saveFileDialog1.FileName ) )
{
foreach (Parameter p in _paramList)
{
String name = p.ParameterName.Trim();
String val = p.ParameterValue.Trim();
foreach (Information i in _infoList)
{
if (p.ParameterName.Trim() == i.SimpleName)
{
name = i.InfoName;
if (i.InputChoice == "1")
{
if (p.ParameterValue == "On")
val = "1";
else
val = "0";
}
break;
}
else if (p.ParameterName.Trim() == i.InfoName)
{
if (p.ParameterValue == "On")
val = "1";
else
val = "0";
break;
}
}
if (name == "location" && val != location_update)
{
name = "location_update";
}
objWriter.WriteLine(name + "=" + val);
}
objWriter.Close();
}
}
I am using Iconic.zip as a way of extracting files on a server but its for a theme pack. And I want to be able to check if a file exists in the zip file before unziping is this possible with the libary.
I am using the following code which works to upload and extract the files.
if (fileUploadZipFiles.HasFile)
{
string uploadedZipFile = Path.GetFileName(fileUploadZipFiles.PostedFile.FileName);
string zipFileLocation = Server.MapPath("~/Themes/" + uploadedZipFile);
fileUploadZipFiles.SaveAs(zipFileLocation);
ZipFile zipFileToExtract = ZipFile.Read(zipFileLocation);
zipFileToExtract.ExtractAll(Server.MapPath("~/Themes/" + txtFolderName.Text.ToString()), ExtractExistingFileAction.DoNotOverwrite);
gridviewExtractedFiles.DataSource = zipFileToExtract.Entries;
gridviewExtractedFiles.DataBind();
lblMessage.Text = "Zip file extracted successfully and containes following files";
}
The second part of this question is that I am using master pages for my themes how would i go about setting the active theme to the one the user wants to make acitve. I am sure I have to have my own base page.
I found the anser to my first part of question was to use the following.
if (fileUploadZipFiles.HasFile)
{
string uploadedZipFile = Path.GetFileName(fileUploadZipFiles.PostedFile.FileName);
string zipFileLocation = Server.MapPath("~/Themes/" + uploadedZipFile);
fileUploadZipFiles.SaveAs(zipFileLocation);
ZipFile zipFileToExtract = ZipFile.Read(zipFileLocation);
var result = zipFileToExtract.Any(entry => entry.FileName.EndsWith("site.master"));
if (result == true)
{
zipFileToExtract.ExtractAll(Server.MapPath("~/Themes/" + txtFolderName.Text.ToString()), ExtractExistingFileAction.DoNotOverwrite);
gridviewExtractedFiles.DataSource = zipFileToExtract.Entries;
gridviewExtractedFiles.DataBind();
lblMessage.Text = "Zip file extracted successfully and containes following files";
}
else
lblMessage.Text = "Not a vlaid theme file.";
}
As suggested here is the answer i used linq to check the existence of the file.
protected void btnExtractZipFiles_Click(object sender, EventArgs e)
{
if (txtFolderName.Text == "")
{
lblMessage.Text = "A Folder Name must be specified";
}else
if (fileUploadZipFiles.HasFile)
{
string uploadedZipFile = Path.GetFileName(fileUploadZipFiles.PostedFile.FileName);
string zipFileLocation = Server.MapPath("~/Themes/" + uploadedZipFile);
fileUploadZipFiles.SaveAs(zipFileLocation);
ZipFile zipFileToExtract = ZipFile.Read(zipFileLocation);
var result = zipFileToExtract.Any(entry => entry.FileName.EndsWith("default.Master"));
if (result == true)
{
zipFileToExtract.ExtractAll(Server.MapPath("~/Themes/" + txtFolderName.Text.ToString()), ExtractExistingFileAction.DoNotOverwrite);
gridviewExtractedFiles.DataSource = zipFileToExtract.Entries;
gridviewExtractedFiles.DataBind();
lblMessage.Text = "Zip file extracted successfully and containes following files";
SetConfiguration(); //parse the configuration file
}
else
lblMessage.Text = "Not a vlaid theme file.";
}
}
In my app I used OpenFileDialog to select a file from temp location (%temp%). Now when I again use OpenFileDialog, it opens from some other location. This feature is working fine if any folder other than temp is selected.
Is this a bug or a feature or Technical limitation?
I wrote this code.
public string[] OnOpenFile(string filetype)
{
string strReturn = null;
string[] strFilename = null;
System.Windows.Forms.OpenFileDialog fdlg = new System.Windows.Forms.OpenFileDialog();
fdlg.Title = "Select an Excel file to Upload.";
fdlg.Filter = filetype;
fdlg.RestoreDirectory = true;
if (fdlg.ShowDialog() == DialogResult.OK)
{
strFilename = fdlg.FileNames;
}
return strFilename;
}
You can use InitialDirectory property documented at http://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.initialdirectory.aspx
in your example:
fdlg.InitialDirectory = Path.GetTempPath();
Running this C# Proram in LinqPad produces wanted result
void Main()
{
OnOpenFile();
OnOpenFile();
OnOpenFile();
}
public string[] OnOpenFile()
{
string strReturn = null;
string[] strFilename = null;
System.Windows.Forms.OpenFileDialog fdlg = new System.Windows.Forms.OpenFileDialog();
fdlg.Title = "Select an Excel file to Upload.";
//fdlg.Filter = filetype;
fdlg.InitialDirectory = Path.GetTempPath();
fdlg.RestoreDirectory = true;
if (fdlg.ShowDialog() == DialogResult.OK)
{
strFilename = fdlg.FileNames;
}
return strFilename;
}
If you comment
fdlg.InitialDirectory = Path.GetTempPath();
you can achieve wanted behavior.
Each time file is selected in folder, that folder in OpenFileDialog opens.
If you press Cancel you have to handle your selected path diffrently - in some string variable, then when you open OpenFileDialog again you set InitialDirectory
I've got a C# windows forms application where I load XML files and CGM graphics files into my application from an Open File browser. I seem to be able to select a couple of hundred at a time and it works without fault, but any more and a dialog box pops up telling me it can't find file such and such, but only gives half the file name. I'm assuming this is due to a limit on the amount of files that can be selected / processed in one go through the open file dialog.
Does anybody know what that number is, and is there a way around it if i have more than that limit to select at once?
I'm effectively 'importing' the files into my application, whereby using a foreach loop the selected files get moved to another folder, and the application writes to an XML file with all the file names of the files imported (as well as other data on the files).
Below is the entire 'import' method
private void addFilesToCSDBToolStripMenuItem_Click(object sender, EventArgs e)
{
int DMsimported = 0;
int graphicsImported = 0;
if (projectName == "")
{
MessageBox.Show("Please open a project first", "DAWS");
return;
}
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
MessageBox.Show("This process may take several minutes depending on the number of imports", "DAWS");
Application.UseWaitCursor = true;
foreach (string file in openFileDialog1.FileNames)
{
string fileName = Path.GetFileNameWithoutExtension(file); //Gets just the name from the file path
string ext = Path.GetExtension(file.ToLower());
if (ext != ".CGM" && ext != ".cgm")
{
bool exists = xmlFileWriter.checkIfFIleExists(fileName + ext);
if (exists != true)
{
xmlFileWriter.writeDatatoXML(file);
File.Move(file, CSDBpath + projectName + "\\CheckedIN\\" + fileName + ext);
DMsimported = DMsimported + 1;
}
else
{
MessageBox.Show(fileName + " already exists in the CSDB. This file will be skipped.", "DAWS");
}
}
else
{
if (File.Exists(CSDBpath + projectName + "\\Graphics\\" + fileName + ext))
{
if (Properties.Settings.Default.OverwriteGraphics == true)
{
File.SetAttributes(CSDBpath + projectName + "\\Graphics\\" + fileName + ext, FileAttributes.Normal); // need this line in order to set the file attributes. Exception thrown otherwise when system tries to overwrite the file.
File.Delete(CSDBpath + projectName + "\\Graphics\\" + fileName + ext);
File.Copy(file, CSDBpath + projectName + "\\Graphics\\" + fileName + ext); //need to give the option as to whether to delete the existing file or skipp.
}
else
{
MessageBox.Show(fileName + " already exists in the CSDB. This file will be skipped. To enable overwriting tick the checkbox in Preferences", "DAWS");
}
}
else
{
File.Copy(file, CSDBpath + projectName + "\\Graphics\\" + fileName + ext);
}
graphicsImported = graphicsImported + 1;
}
}
Application.UseWaitCursor = false;
buildAllListViews();
copyCGMfilesToDirectories();
if (DMsimported > 0)
{
MessageBox.Show(DMsimported.ToString() + " DM files successfully imported into the CSDB", "DAWS");
}
if (graphicsImported > 0)
{
MessageBox.Show(graphicsImported.ToString() + " graphic files successfully imported into the CSDB", "DAWS");
}
if (graphicsImported == 0 && DMsimported == 0)
{
MessageBox.Show("No files imported", "DAWS");
}
updateMainFilesList();
}
}
According to this article, you will receive a "Too many files selected" error message when you use the OpenFileDialog control to select more than 200 files.
Just tested in .NET 4.5, no problem with 5000 files, so it looks like it depends on .net framework/os version (I've used long enough file names, just to be sure, that it does not depend on some old windows constraint, like max length of all file names is 65536 or 32768):
var directory = #"c:\test\test";
Directory.CreateDirectory(directory);
for (int i = 0; i < 5000; i++)
{
var path = Path.Combine(directory, i.ToString() + new string('a', 200));
File.WriteAllText(path, "");
}
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
var fileCount = openFileDialog1.FileNames;
var lastFileName = openFileDialog1.FileNames[4999];
}
In .NET Framework 1.1, for the OpenFileDialog.Multiselect Property:
There is a hard-coded limit of 200 files that can be opened with the
Open File dialog box. For more information about this limitation, see
article 820631, "PRB: 'Too Many Files Selected' Error Message Occurs
When You Use the OpenFileDialog Control", in the Microsoft Knowledge
Base at http://support.microsoft.com.
When you have to work with such a large number of files, maybe it makes more sense to select only the folder (even more reasonable if you select all the files in the folder, if this is your case). Try using the FolderBrowserDialog Class:
var folderBrowserDialog = new FolderBrowserDialog();
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
var fi = new DirectoryInfo(folderBrowserDialog.SelectedPath);
// here you get the files collection
var files = fi.GetFiles();
}
Try:
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
openFileDialog1.Multiselect = false;
var fileCount = openFileDialog1.FileNames;
var lastFileName = openFileDialog1.FileNames[4999];
}