Using NPOI version 2.1.3.1, this line works perfectly, returning a a byte array with data:
workbook is an XSSFWorkbook
using (var memoryStream = new MemoryStream())
{
workbook.Write(memoryStream);
return memoryStream.ToArray();
}
when upgrading to 2.2 (and 2.3), this no longer returns any data, the byte array has 0 bytes.
no exceptions are thrown, it just silently fails to write data.
Is there a new way to write this workbook out in the updated version?
I don't see any issue in your code. In fact I am using similar approach to get the result. Try type casting your returned value with MemoryStream class or define memorystream variable as type MemoryStream.
Below is my approach
public MemoryStream GetExcelStream()
{
MemoryStream ms = null;
using (ms = new MemoryStream())
{
workbook.Write(ms);
}
return ms;
}
MemoryStream excelMS = GetExcelStream();
..........................
Response.BinaryWrite(excelMS.ToArray());
Response.End();
If above approach doesn't work, see this link as well NPOI writes 0 bytes in the MemoryStream
Related
I need to create a WebAPI method which downloads a file. The file is being correctly downloaded, however the download seems to remain stuck at almost 100% percent in the client browser (ie it doesn't terminate although the file would have downloaded and can be opened). It remains like that for a couple of minutes before terminating. What could the problem be? The following is some test code which replicates my issue
[HttpGet]
public HttpResponseMessage GetFile()
{
string fileName = #"c:\temp\test.zip";
MemoryStream responseStream = new MemoryStream();
using (FileStream source = File.Open(fileName, FileMode.Open))
source.CopyTo(responseStream);
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StreamContent(responseStream);
response.StatusCode = HttpStatusCode.OK;
response.Content.Headers.ContentType = new MediaTypeHeaderValue(ContentTypeHelper.Instance.GetFileContentType(fileName));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentLength = responseStream.Length;
return response;
}
Looks like you need to rewind the MemoryStream after copying:
MemoryStream responseStream = new MemoryStream();
using (FileStream source = File.Open(fileName, FileMode.Open))
source.CopyTo(responseStream);
responseStream.Seek(0, SeekOrigin.Begin);
I've a method on my Web Api Controller that returns MemoryStream. Problem occurs when JsonMediaTypeFormatter is selected by DefaultContentNegotiator and WriteToStreamAsync is called. (I'm using default media type formatters)
Newtonsoft.Json.JsonSerializationException: Error getting value from 'MemStreamMaxLength on 'System.IO.MemoryStream'
Following code simulates the situation:
var stream = new MemoryStream();
stream.WriteByte(1);
stream.Position = 0;
var formatter = new JsonMediaTypeFormatter();
var writeStream = new MemoryStream();
formatter.WriteToMemoryStreamAsync(stream.GetType(), stream, writeStream, null, null).Wait();
My encryption code is
{
AesManaged aes = null;
MemoryStream memoryStream = null;
CryptoStream cryptoStream = null;
try
{
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt), 10000);
aes = new AesManaged();
aes.Key = rfc2898.GetBytes(32);
aes.IV = rfc2898.GetBytes(16);
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
return Convert.ToBase64String(memoryStream.ToArray());
}
finally
{
if (cryptoStream != null)
cryptoStream.Close();
if (memoryStream != null)
memoryStream.Close();
if (aes != null)
aes.Clear();
}
}
I just tried Code Analysis its giving me
CA2202
Do not dispose objects multiple times
Object 'memoryStream' can be disposed more than once in method 'EncryptDecrypt.Encrypt(string, string, string)'.
To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.
But my code is working fine I created memoryStream & cryptoStream & closed them after... but I am not able to understand why is it telling me multiple objects multiple times
The guidelines for IDisposable state that disposing the same object twice should have no effect the second time.
However, not all implementations follow this guideline, so Code Analysis tells you not to rely on it.
Your particular objects are safe in this regard, so you don't have an actual problem.
I've verified using System.Text.Encoding.ASCII.GetString(ms.ToArray)); that my memorystream has the expected data.
However using the LinqToCSV nuget library will not generate my csv file. I get no errors or exceptions thrown. I just get an empty file when I'm prompted to open the file.
Here is my Action Method
public FileStreamResult Export(){
var results = _service.GetProperties().Take(3);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.TextWriter txt = new System.IO.StreamWriter(ms);
CsvFileDescription inputFileDescription = new CsvFileDescription{
SeparatorChar =',',
FirstLineHasColumnNames = true
}
;
CsvContext csv = new CsvContext();
csv.Write(results,txt,inputFileDescription);
return File(ms , "application/x-excel");
}
I find it interesting, if I change the return type to contentResult, and the return method to Content() and pass it System.Text.Encoding.ASCII.GetString(ms.ToArray)); I do get a browser window showing my data.
Make sure you reset stream position to 0. Also make sure you flush your StreamWriter before that.
Calling the Web API method to return CVS file from JavaScript.
public HttpResponseMessage Bidreport([FromBody]int formData).....
Fill in your IEnumerable<YourObject>query = from LINQ query
....
This is how to return it:
using (var ms = new MemoryStream())
{
using (TextWriter txt = new StreamWriter(ms))
{
var cc = new CsvContext();
cc.Write(query, txt, outputFileDescription);
txt.Flush();
ms.Position = 0;
var fileData = Encoding.ASCII.GetString(ms.ToArray());
var result = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent(fileData)};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-excel");
return result;
}
}
I am using C# and a console app and I am using this script to download files from a remote server. There area a couple of things I want to add. First, when it writes to a file, it doesn't take into consideration a newline. This seems to run a certain amount of bytes and then goes to a newline. I would like it to keep the same format as the file it is reading from. Second, there are multiple .jpg files on the server that I need to download. How can I use this script to download multiple, .jpg files
public static int DownLoadFiles(String remoteUrl, String localFile)
{
int bytesProcessed = 0;
// Assign values to these objects here so that they can
// be referenced in the finally block
StreamReader remoteStream = null;
StreamWriter localStream = null;
WebResponse response = null;
// Use a try/catch/finally block as both the WebRequest and Stream
// classes throw exceptions upon error
try
{
// Create a request for the specified remote file name
WebRequest request = WebRequest.Create(remoteUrl);
request.PreAuthenticate = true;
NetworkCredential credentials = new NetworkCredential("id", "pass");
request.Credentials = credentials;
if (request != null)
{
// Send the request to the server and retrieve the
// WebResponse object
response = request.GetResponse();
if (response != null)
{
// Once the WebResponse object has been retrieved,
// get the stream object associated with the response's data
remoteStream = new StreamReader(response.GetResponseStream());
// Create the local file
localStream = new StreamWriter(File.Create(localFile));
// Allocate a 1k buffer
char[] buffer = new char[1024];
int bytesRead;
// Simple do/while loop to read from stream until
// no bytes are returned
do
{
// Read data (up to 1k) from the stream
bytesRead = remoteStream.Read(buffer, 0, buffer.Length);
// Write the data to the local file
localStream.WriteLine(buffer, 0, bytesRead);
// Increment total bytes processed
bytesProcessed += bytesRead;
} while (bytesRead > 0);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Close the response and streams objects here
// to make sure they're closed even if an exception
// is thrown at some point
if (response != null) response.Close();
if (remoteStream != null) remoteStream.Close();
if (localStream != null) localStream.Close();
}
// Return total bytes processed to caller.
return bytesProcessed;
Why don't you use WebClient.DownloadData or WebClient.DownloadFile instead?
WebClient client = new WebClient();
client.Credentials = new NetworkCredentials("id", "pass");
client.DownloadFile(remoteUrl, localFile);
By the way the correct way to copy a stream to another is not what you did. You shouldn't read into char[] at all, as you might run into encoding and end of line issues as you are downloading a binary file. The WriteLine method call is problematic too. The right way to copy contents of a stream to another is:
void CopyStream(Stream destination, Stream source) {
int count;
byte[] buffer = new byte[BUFFER_SIZE];
while( (count = source.Read(buffer, 0, buffer.Length)) > 0)
destination.Write(buffer, 0, count);
}
The WebClient class is much easier to use and I suggest using that instead.
The reason you're getting spurious newlines in the result file is because StreamWriter.WriteLine() puts them there. Try using StreamWriter.Write() instead.
Regarding downloading multiple files, can't you just run the function several times, passing it the URLs of the different files you need?