I have a byte array for a file, is there a way to take that and save it has a file to a remote file server?
File.WriteAllBytes(#"\\server\public_share\MyFile.txt", byteArray);
Writing your data to file is the simple part and #aaron has shown you how...
i.e. File.WriteAllBytes(....etc
But something to be aware of, if you're transferring binary data over the wire and if your data contains bytes that could be interpreted as control characters then your data transfer will be problematic.
What you may need to do is encode your data first so that you can transfer it safely, typically you would use something like Base64 encoding.
You can use the Convert helper class to do that...
Convert.ToBase64String("file contents");
If you are doing this in the codebehind then you will need to use the FileStream and BinaryWriter objects.
Something like this;
FileStream filestream = new FileStream("myfile.txt", FileMode.Open);
BinaryReader br = new BinaryReader(filestream);
String msg = br.ReadString();
br.Close();
filestream.Close();
FileStream networkStream = new FileStream(#"\\server\share\file.txt", FileMode.Create);
BinaryWriter bw = new BinaryWriter(filestream);
bw.Write(msg);
bw.Close();
networkStream.Close();
If you're passing it through Javascript maybe using a HTML browse button then you'll need to do the same sort of thing but you will get the file stream from the post form request.
You may have an issue writing to the network location, if you're using IIS then you could set up a virtual directory and set the credentials in IIS. The alternative is that you will need to do impersonation to write the file to the network server.
Mike
Related
I use a webservice that returns a zip file, as a string, and not bytes as I expected. I tried to write it to the disk, but when I open it, it tells me that it is corrupt. What am I doing wrong?
string cCsv = oResponse.fileCSV;//this is the result from webservice
MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(cCsv));
using (FileStream file = new FileStream("test.zip", FileMode.Create, FileAccess.Write))
{
ms.WriteTo(file);
}
ms.Close();
I'm not sure what kind of encoding the string is in, but assuming UTF-8, the following should work. UTF-16 would be another guess.
string cCsv = oResponse.fileCSV;
using (BinaryWriter bw = new BinaryWriter(File.Create("test.zip")))
{
bw.Write(System.Text.Encoding.UTF8.GetBytes(cCsv));
}
It'd be informative to look at the characters and the raw string itself being returned.
Edit
Per Frank's answer, the correct encoding is base64, which of course makes sense because it's binary data stored as a string.
Also, per Frank's answer, if the only action is to directly write a single byte array, then File.WriteAllBytes is more compact.
Ok, i solve the problem:
File.WriteAllBytes("testbase64.zip", Convert.FromBase64String(cCsv));
This is what i would like to do:
Get a 64base byte array from database (which is actually in pdf format). This works.
Then i would like to show the pdf in a webbrowser component.
I first started with saving the pdf to a file.pdf and then open it:
byte[] bitjes = isc.GetFileById(fileid); // Getting the bytes
FileStream stream = new FileStream(#"C:\NexusPDF\" + filename, FileMode.CreateNew);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(bitjes, 0, bitjes.Length);
writer.Close();
webBrowser.Navigate(#"C:\NexusPDF\" + filename);
But that gave me all sorts of problems involving read/write acces. So i figured i have to use the memorystream class to solve this problem.
byte[] bitjes = isc.GetFileById(fileid);
MemoryStream memstream = new MemoryStream(bitjes);
BinaryWriter writer = new BinaryWriter(memstream);
writer.Write(bitjes, 0, bitjes.Length);
writer.Close();
But here's where i'm stuck! I can't just show this in a webBrowser component can i?
Do i have to use the binaryreader before i can show the pdf?
Am i approaching this problem the right way, or are there better alternatives?
Main thing is that i don't want to save the file on disk.
Any help will be appreciated.
You may be able to use the data URL scheme. This URL scheme specifies the content inline.
webBrowser.Navigate("data:application/pdf;base64," + X);
Where X is the base 64 string.
No need to convert the base 64 PDF string into a byte array!
See http://www.ietf.org/rfc/rfc2397.txt for more details.
Is it possible to open a file directly from a MemoryStream opposed to writing to disk and doing Process.Start() ? Specifically a pdf file? If not, I guess I need to write the MemoryStream to disk (which is kind of annoying). Could someone then point me to a resource about how to write a MemoryStream to Disk?
It depends on the client :) if the client will accept input from stdin you could push the dta to the client. Another possibility might be to write a named-pipes server or a socket-server - not trivial, but it may work.
However, the simplest option is to just grab a temp file and write to that (and delete afterwards).
var file = Path.GetTempFileName();
using(var fileStream = File.OpenWrite(file))
{
var buffer = memStream.GetBuffer();
fileStream.Write(buffer, 0, (int)memStream.Length);
}
Remember to clean up the file when you are done.
Path.GetTempFileName() returns file name with '.tmp' extension, therefore you cant't use Process.Start() that needs windows file association via extension.
If by opening a file, you mean something like starting Adobe Reader for PDF files, then yes, you have to write it to a file. That is, unless the application provides you with some API do that.
One way to write a stream to file would be:
using (var memoryStream = /* create the memory stream */)
using (var fileStream = File.OpenWrite(fileName))
{
memoryStream.WriteTo(fileStream);
}
I am using the following C# code to compress a file:
// Open the stream we want to compress
FileStream fs = File.Create(#"C:\Projects\Samples\test\compressed.zip", 0);
// Creates the GZipStream
GZipStream gzip = new GZipStream(fs, CompressionMode.Compress);
// Reading the content to compress
byte[] bytes = File.ReadAllBytes(#"C:\Projects\Samples\samplefile.xml");
// Writing compressed content
gzip.Write(bytes, 0, bytes.Length);
gzip.Close(); // This also closes the FileStream (the underlying stream)
However, when I extract the file from windows explorer the file loses it's extension so instead of samplefile.xml it just becomes samplefile. Same thing happened with .txt file not just .xml file.
Can you help me see what I'm doing wrong?
ok found the problem:
Line 2 has to be as follows:
FileStream fs = File.Create(#"C:\Projects\Samples\test\compressed.xml.zip", 0);
GZipStream doesn't create zip archives. It creates a gzip file, which contains only one file, and doesn't necessarily store a filename at all. Normally you should use the .gz extension to identify a gzip file, and it's conventional to use the entire name of the original file with .gz appended on the end. See also here for more information about gzip format: http://en.wikipedia.org/wiki/Gzip#File_format
If you actually want to create zip archives, you might want to use a library like SharpZipLib: http://www.icsharpcode.net/opensource/sharpziplib/
I am building some C# desktop application and I need to save file into database. I have come up with some file chooser which give me correct path of the file. Now I have question how to save that file into database by using its path.
It really depends on the type and size of the file. If it's a text file, then you could use File.ReadAllText() to get a string that you can save in your database.
If it's not a text file, then you could use File.ReadAllBytes() to get the file's binary data, and then save that to your database.
Be careful though, databases are not a great way to store heavy files (you'll run into some performance issues).
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
int numBytes = new FileInfo(fileName).Length;
byte[] buff = br.ReadBytes(numBytes);
Then you upload it to the DB like anything else, I'm assume you are using a varbinary column (BLOB)
So filestream would be it but since you're using SQL 2K5 you will have to do it the read into memory way; which consumes alot of resources.
First of the column type varchar(max) is your friend this give you ~2Gb of data to play with, which is pretty big for most uses.
Next read the data into a byte array and convert it to a Base64String
FileInfo _fileInfo = new FileInfo(openFileDialog1.FileName);
if (_fileInfo.Length < 2147483647) //2147483647 - is the max size of the data 1.9gb
{
byte[] _fileData = new byte[_fileInfo.Length];
_fileInfo.OpenRead().Read(_fileData, 0, (int)_fileInfo.Length);
string _data = Convert.ToBase64String(_fileData);
}
else
{
MessageBox.Show("File is too large for database.");
}
And reverse the process to recover
byte[] _fileData = Convert.FromBase64String(_data);
You'll want to dispose of those strings as quickly as possible by setting them to string.empty as soon as you have finished using them!
But if you can, just upgrade to 2008 and use FILESTREAM.
If you're using SQL Server 2008, you could use FILESTREAM (getting started guide here). An example of using this functionality from C# is here.
You would need the file into a byte array then store this as a blob field in the database possible with the name you wanted to give the file and the file type.
You could just reverse the process for putting the file out again.