I'm using StreamWriter to generate a dynamic file and holding it in a MemoryStream. Everything appears to be alright until I go to save the file using rebex sftp.
The example they give on their site works fine:
// upload a text using a MemoryStream
string message = "Hello from Rebex FTP for .NET!";
byte[] data = System.Text.Encoding.Default.GetBytes(message);
System.IO.MemoryStream ms = new System.IO.MemoryStream(data);
client.PutFile(ms, "message.txt");
However the code below does not:
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
writer.Write("test");
}
client.PutFile(stream, "test.txt");
}
The file "test.txt" is saved, however it is empty. Do I need to do more than just enable AutoFlush for this to work?
After writing to the MemoryStream, the stream is positioned at the end. The PutFile method reads from the current position to the end. That's exactly 0 bytes.
You need to position the stream at the beginning before passing it to PutFile:
...
}
stream.Seek(0, SeekOrigin.Begin);
client.PutFile(stream, "test.txt");
You may also need to prevent the StreamWriter from disposing the MemoryStream:
var writer = new StreamWriter(stream);
writer.Write("test");
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
client.PutFile(stream, "test.txt");
Related
I'm using the DryWetMidi library to process some MIDI data.
First I get the MIDI Data as a MemoryStream from the Clipboard:
MemoryStream ms = (MemoryStream)Clipboard.GetDataObject().GetData("Standard MIDI File");
MidiFile mid = MidiFile.Read(ms);
Then I do some stuff with the midi:
mid.RemoveNotes(n => n.NoteName == NoteName.FSharp);
Now I want to write it back to the Clipboard. I managed to do this like this:
using (FileStream file = new FileStream("file.mid", FileMode.Create, FileAccess.
{
mid.Write(file);
}
using (MemoryStream ms2 = new MemoryStream())
using (FileStream file = new FileStream("file.mid", FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms2.Write(bytes, 0, (int)file.Length);
Clipboard.Clear();
Clipboard.SetData(midiFormat, ms2);
}
File.Delete("file.mid");
As you can see, first I write the MIDI to a file, then I read that file into a MemoryStream which I then write into the Clipboard. This makes not much sense, because it would be simpler to write it to a MemoryStream directly. Also, I don't want to write a file to the users file system. But there's the problem. I tried it like this:
using (MemoryStream ms2 = new MemoryStream())
{
mid.Write(ms2);
}
This doesn't give me an error, but the MemoryStream is completely empty. Calling ms2.Length results in a System.ObjectDisposedException.
How can I write the midi directly into the MemoryStream?
EDIT: Here's the link to the DryWetMidi Write() Method.
Second Edit: Here's a piece of code that won't work:
MemoryStream ms = (MemoryStream)Clipboard.GetDataObject().GetData(midiFormat);
MidiFile mid = MidiFile.Read(ms);
mid.RemoveNotes(n => n.NoteName == NoteName.FSharp);
MemoryStream ms2 = new MemoryStream();
mid.Write(ms2);
var T = ms2.Length; //This will throw an exception
Third Edit: I am 100% sure that the code posted is exactly the same I'm running. Here's the StackTrace. (Gist because formatting was terrible on SO).
As far as I can see, DryWetMidi uses BinaryWriter to write to stream. And the default behaviour of BinaryWriter is that when it is disposed, It'll dispose the stream as well.
You can't read from MemoryStream when it's disposed but you can call ToArray().
byte[] result;
using (MemoryStream ms2 = new MemoryStream())
{
mid.Write(ms2);
result = ms2.ToArray();
}
Im trying to prompt a downloadable text file (.txt), but I get this error:
Cannot access a closed Stream.
I have looked at simular questions in here:
Cannot Access Closed Stream
But it was not very useful.
Here is my code:
private FileStreamResult Export()
{
string name = "filename.txt";
MemoryStream stream = new MemoryStream();
using (StreamWriter writer = new StreamWriter(stream))
{
StringBuilder sb = new StringBuilder();
sb.Append("A text...");
writer.WriteLine(sb.ToString());
}
return File(stream, "text/plain", name);
}
UPDATE (working copy):
This gives me an blank text file.
private FileResult Export()
{
string name = "filename.txt";
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
StringBuilder sb = new StringBuilder();
sb.Append("A text...");
writer.WriteLine(sb.ToString());
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "text/plain", name);
}
That is correct, when you wrap a stream in another stream, calling .Close() or .Dispose() on any of them will dispose the whole stream. In this case, wrapping the MemoryStream in a StreamWriter means that when the using statement completes the StreamWriter and MemoryStream are both disposed.
My guess is since you are returning a FileStreamResult the encapsulating File will close the stream for you after the stream is no longer used. In this case, you do not want to use the using statement and will want to leave the stream open when returning it.
UPDATE
Since a stream is forward access you'll need to see the stream back to the beginning to allow the data to be read back out.
stream.Seek(0, SeekOrigin.Begin);
Just remove that using statement - you are passing disposed object reference to File method and you that's the reason why you get exception. From MSDN,
The StreamWriter object calls Dispose on the provided Stream object
when StreamWriter.Dispose is called.
I believe File will dispose stream by itself after usage (not verified by looking at source code).
UPDATE:
writer.Flush(); before return statement should help you
You have to set the position of the memorystream to 0 before using it in your FileStreamResult, otherwise it will be read from current position (IE the end of the stream).
stream.Position = 0;
return File(stream, "text/plain", name);
Just had the same thing.
I know this thread is ancient, just hoping to aid others having the same issue.
Replace the FileStreamResult type on your action with FileResult.
I have such method to load document file from db that is stored as binary and then replace customxml parts with parameters.
Somehow when i convert byte into MemoryStream then process it doesn't work, my custom xml parts are not replaced. But if i use FileStream and read same file from disk then it replaced perfectly!
What is wrong with MemoryStream? i can't also cast MemoryStream to FileStream or create instrance of Stream or etc..
Any suggestion?
private static Stream LoadContent(byte[] content, XmlDocument parameters)
{
//FileStream works perfectly
//Stream fileStream = new FileStream(#"C:\temp\test.docx", FileMode.Open);
Stream documentStream = new MemoryStream();
documentStream.Write(content, 0, content.Length);
//Processes word file, replace custom xml parts with parameters
using (WordprocessingDocument document = WordprocessingDocument.Open(documentStream, true))
{
MainDocumentPart mainPart = document.MainDocumentPart;
Stream partStream = mainPart.CustomXmlParts.First().GetStream();
using (XmlWriter xmlWriter = XmlWriter.Create(partStream, new XmlWriterSettings { CloseOutput = false }))
{
parameters.WriteTo(xmlWriter);
xmlWriter.Flush();
}
mainPart.Document.Save();
}
return documentStream;
}
You might want to try to set the 'Position' propery of the memorystream to 0 after writing data to it and before reading it again.
Alernatively you can also pass the byte array to the constructor of the memorystream instead of calling writer.
edit
I see according to MSDN that the 'Document.Save' method will flush the stream to allow propper saving. ( http://msdn.microsoft.com/en-us/library/cc840441.aspx ).
However MemoryStream wont do anything on flush ( http://msdn.microsoft.com/en-us/library/system.io.memorystream.flush.aspx ).
You could try to create a new MemoryStream and then pass that as a parameter to the 'Document.Save' method.
How can i create a file and write to it using the memory stream?
I need to use the memorystream to prevent other threads from trying to access the file.
The data i'm trying to save to a file is html.
How can this be done?
(Presuming you mean how to copy a file's content to a memory stream)
If you are using framework 4:
var memoryStream = new MemoryStream();
using var fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
fileStream.CopyTo(memoryStream);
Here are code to create file
byte[] data = System.Text.Encoding.ASCII.GetBytes("This is a sample string");
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ms.Write(data, 0, data.Length);
ms.Close();
I am trying to create a pdf file with iTextSharp. My attempt writes the content of the pdf to a MemoryStream so I can write the result both into file and a database BLOB. The file gets created, has a size of about 21kB and it looks like a pdf when opend with Notepad++. But my PDF viewer says it's currupted.
Here is a little code snippet (only tries to write to a file, not to a database):
Document myDocument = new Document();
MemoryStream myMemoryStream = new MemoryStream();
PdfWriter myPDFWriter = PdfWriter.GetInstance(myDocument, myMemoryStream);
myDocument.Open();
// Content of the pdf gets inserted here
using (FileStream fs = File.Create("D:\\...\\aTestFile.pdf"))
{
myMemoryStream.WriteTo(fs);
}
myMemoryStream.Close();
Where is the mistake I make?
Thank you,
Norbert
I think your problem was that you weren't properly adding content to your PDF. This is done through the Document.Add() method and you finish up by calling Document.Close().
When you call Document.Close() however, your MemoryStream also closes so you won't be able to write it to your FileStream as you have. You can get around this by storing the content of your MemoryStream to a byte array.
The following code snippet works for me:
using (MemoryStream myMemoryStream = new MemoryStream()) {
Document myDocument = new Document();
PdfWriter myPDFWriter = PdfWriter.GetInstance(myDocument, myMemoryStream);
myDocument.Open();
// Add to content to your PDF here...
myDocument.Add(new Paragraph("I hope this works for you."));
// We're done adding stuff to our PDF.
myDocument.Close();
byte[] content = myMemoryStream.ToArray();
// Write out PDF from memory stream.
using (FileStream fs = File.Create("aTestFile.pdf")) {
fs.Write(content, 0, (int)content.Length);
}
}
I had similar issue. My file gets downloaded but the file size will be 13Bytes. I resolved the issue when I used binary writer to write my file
byte[] bytes = new byte[0];
//pass in your API response into the bytes initialized
using (StreamWriter streamWriter = new StreamWriter(FilePath, true))
{
BinaryWriter binaryWriter = new BinaryWriter(streamWriter.BaseStream);
binaryWriter.Write(bytes);
}
Just some thoughts - what happens if you replace the memory stream with a file stream? Does this give you the result you need? This will at least tell you where the problem could be.
If this does work, how do the files differ (in size and binary representation)?
Just a guess, but have you tried seeking to the beginning of the memory stream before writing?
myMemoryStream.Seek(0, SeekOrigin.Begin);
Try double checking your code that manipulates the PDF with iText. Make sure you're calling the appropriate EndText method of any PdfContentByte objects, and make sure you call myDocument.Close() before writing the file to disk. Those are things I've had problems with in the past when generating PDFs with iTextSharp.
documentobject.Close();
using (FileStream fs = System.IO.File.Create(path)){
Memorystreamobject.WriteTo(fs);
}