I have read the posts on this subject but none of them explains it to me clearly enough to be able to fix the problem.
I am trying to upload a file from a local directory to the server.
Here is my code:
string fullPath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory + #"Images\Readings", PhotoFileName);
Stream s = System.IO.File.OpenRead(fileUpload);
byte[] buffer = new byte[s.Length];
s.Read(buffer, 0, Convert.ToInt32(s.Length));
using (FileStream fs = new FileStream(fullPath, FileMode.Create))
{
fs.Write(buffer, 0, Convert.ToInt32(fs.Length));
Bitmap bmp = new Bitmap((Stream)fs);
bmp.Save(fs, ImageFormat.Jpeg);
}
I keep on getting an Argument Exception: "Parameter is not valid" on line:
Bitmap bmp = new Bitmap((Stream)fs);
Can anyone explain this to me please
There are at least two problems, probably three. First, your copying code is broken:
byte[] buffer = new byte[s.Length];
s.Read(buffer, 0, Convert.ToInt32(s.Length));
You've assumed that this will read all of the data in a single Read call, and ignored the return value for Read. Generally, you'd need to loop round, reading data and writing it (the amount you've just read) to the output stream, until you read the end. However, as of .NET 4, Stream.CopyTo makes this much simpler.
Next is how you're creating the bitmap:
using (FileStream fs = new FileStream(fullPath, FileMode.Create))
{
fs.Write(buffer, 0, Convert.ToInt32(fs.Length));
Bitmap bmp = new Bitmap((Stream)fs);
bmp.Save(fs, ImageFormat.Jpeg);
}
You're trying to read from the stream when you've just written to it - but without "rewinding"... so there's no more data left to read.
Finally, I would strongly advise against using Bitmap.Save to write to the same stream that you're loading the bitmap from. Bitmap will keep a stream open, and read from it when it needs to - if you're trying to write to it at the same time, that could be very confusing.
It's not clear why you're using Bitmap at all, to be honest - if you're just trying to save the file that was uploaded, without any changes, just use:
using (Stream input = File.OpenRead(fileUpload),
output = File.Create(fullPath))
{
input.CopyTo(output);
}
This is assuming that fileUpload really is an appropriate filename - it's not clear why you haven't just written the file to the place you want to write it to straight away, to be honest. Or use File.Copy to copy the file. The above code should work with any stream, so you can change it to save the stream straight from the request...
Related
I have an image in the png format which I would like to load and convert to a bmp stream. The code I'm using to achieve this is the following:
// Image.FromFile yields the same result.
FileStream originalFile = File.Open("image.png", FileMode.Open);
System.Drawing.Image fileImage = System.Drawing.Image.FromStream(originalFile);
MemoryStream bmpStream = new MemoryStream();
fileImage.Save(bmpStream, System.Drawing.Imaging.ImageFormat.Bmp);
Result: https://pastebin.com/raw/p1TBjnD1
However the stream this produces is different from when saving to a file and opening it like this:
FileStream originalFile = File.Open("image.png", FileMode.Open);
System.Drawing.Image fileImage = System.Drawing.Image.FromStream(originalFile);
FileStream bmpStream;
fileImage.Save("image.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
bmpStream = File.Open("image.bmp", FileMode.Open);
Result: https://pastebin.com/raw/vSdRwZpL
There appears to be some kind of header missing when saving to a stream. Why is this, and how can I easily add it to my streams without having to save to files?
My question is not how to do this, but why the stream doesn't include this header while the file does.
They are not different but when you dump or copy or do something else with memory stream you always have to reset it to its initial position.
fileImage.Save(bmpStream, System.Drawing.Imaging.ImageFormat.Bmp);
bmpStream.Position = 0
... now you can dump or save to file from bmpStream
If you do not reset the position, you might read nothing back from the MemoryStream. In the case of Image.Save(), it is even more tricky because the Save method puts the MemoryStream position at the beginning of the image data (after the header) assuming this is what you want.
I Have gif image in base64.
Currently I am approaching this way. reading base64 gif file and writing it to byte array and writing it back to image file to disk and reading from the file to picturebox.image.
byte[] imageBytes = Convert.FromBase64String(body);
//* this is write file to disk and read
string filename = Username;
File.WriteAllBytes(filename, imageBytes);
fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
pictureBox1.Image = Image.FromStream(fs);
Now, I want to write it to memory without writing it to disk file. like in a form of variable image. that can be assigned to picturebox. Is there any possible of this. because I have to do repeatedly many times for many images.
So I would like find a different approach without writing saving file to disk and reading it again.
Any help appreciated.
byte[] imageBytes = Convert.FromBase64String(body);
MemoryStream stream = new MemoryStream(imageBytes);
pictureBox1.Image = Image.FromStream(stream);
byte[] imageBytes = Convert.FromBase64String(body);
using (var ms = new MemoryStream(imageBytes))
{
pictureBox1.Image = Image.FromStream(ms);
}
Be aware the MemoryStream class is IDisposable so you should Dispose() it. This can happen with using or with try/catch/finally block.
I'm working in a project that doesn't use much of the .net framework and instead work with Request.Form posts.
The code that was being used to save the images (this work, but loss quality) is this one:
files[0].SaveAs(HttpContext.Current.Server.MapPath("../uploads/") + filename);
So I tried to change to this, but now it doesn't even save the image. (the uploadStream.Read(buffer, 0, buffer.Length) comes with the value of 0.
string imagePath = HttpContext.Current.Server.MapPath("../uploads/") + filename;
using (BinaryReader uploadStream = new BinaryReader(files[0].InputStream))
{
using (FileStream fileStream = new FileStream(imagePath, FileMode.Create))
{
byte[] buffer = new byte[32768];
int read;
while ((read = uploadStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, read);
}
}
}
I built this code basing myself on the question/answers of Image upload without loss of quality. I'm using .net 4.0 on the application.
Is there another way, or what I was doing is the right way and I just missed something? PS: I don't get any error and on the database, I save the correct information, but I don't get the file on the folder. The upload to that folder works, since it work with the SaveAs() method.
PS: I may be wrong, about SaveAs being the reason to loss of quality on the image, but the files[0] come right from the HttpFileCollection and the upload is only there.
I got a file stream which has content read from a disk.
Stream input = new FileStream("filename");
This stream is to be passed to a third party library which after reading the stream, keeps the Stream's position pointer at the end of the file (as ususal).
My requirement is not to load the file from the desk everytime, instead I want to maintain MemoryStream, which will be used everytime.
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
}
I have tried the above code. It works for the first very time to copy the input stream to output stream, but subsequent calls to CopyStream will not work as the source's Position will be at the end of the stream after the first call.
Are there other alternatives which copy the content of the source stream to another stream irrespective of the source stream's current Position.
And this code needs to run in thread safe manner in a multi threaded environment.
You can use .NET 4.0 Stream.CopyTo to copy your steam to a MemoryStream. The MemoryStream has a Position property you can use to move its postition to the beginning.
var ms = new MemoryStream();
using (Stream file = File.OpenRead(#"filename"))
{
file.CopyTo(ms);
}
ms.Position = 0;
To make a thread safe solution, you can copy the content to a byte array, and make a new MemoryStream wrapping the byte array for each thread that need access:
byte[] fileBytes = ms.ToArray();
var ms2 = new MemoryStream(fileBytes);
You should check the input stream's CanSeek property. If that returns false, you can only read it once anyway. If CanSeek returns true, you can set the position to zero and copy away.
if (input.CanSeek)
{
input.Position = 0;
}
You may also want to store the old position and restore it after copying.
ETA: Passing the same instance of a Stream around is not the safest thing to do. E.g. you can't be sure the Stream wasn't disposed when you get it back. I'd suggest to copy the FileStream to a MemoryStream in the beginning, but only store the byte content of the latter by calling ToArray(). When you need to pass a Stream somewhere, just create a new one each time with new MemoryStream(byte[]).
I am using a third party tool to get the scanned content from the scanner. On button click it executes the code and gives the content as a FileStream. Now I need to save this FileStream content as a pdf file in to a specified folder.
After saving I need to open the file in browser. How can I save the FileStream as a PDF file?
You can write the stream directly to the output buffer of the response.
So if you're at the point in your code where you have the filestream from the scanner. Simply read bytes from the scanner filestream and write them to the Response.OutputStream
Set the contentType to application/pdf
Make sure you return nothing else. The users browser will do whatever it is configured to do now, either save to disk or show in the browser. You can also save to disk on the server at this point as well in case you wanted a backup.
I'm assuming your file stream is already a pdf, otherwise you'll need to use something like itextsharp to create the pdf.
Edit
Here's some rough and ready code to do it. You'll want to tidy this up, like adding exception trapping to make sure the file stream gets cleaned up properly.
public void SaveToOutput(Stream dataStream)
{
dataStream.Seek(0, SeekOrigin.Begin);
FileStream fileout = File.Create("somepath/file.pdf");
const int chunk = 512;
byte[] buffer = new byte[512];
int bytesread = dataStream.Read(buffer,0,chunk);
while (bytesread == chunk)
{
HttpContext.Current.Response.OutputStream.Write(buffer, 0, chunk);
fileout.Write(buffer, 0, chunk);
bytesread = dataStream.Read(buffer, 0, chunk);
}
HttpContext.Current.Response.OutputStream.Write(buffer, 0, bytesread);
fileout.Write(buffer, 0, bytesread);
fileout.Close();
HttpContext.Current.Response.ContentType = "application/pdf";
}
Simon
You might want to take a look at the C# PDF Library on SourceForge: http://sourceforge.net/projects/pdflibrary/
If I'm understanding you correctly, the third party library is handing you a stream containing the data for the scanned document and you need to write it to a file? If that's the case you need to look up file I/O in C#. Here's a link and an example:
Stream sourceStream = scanner.GetOutput(); // whereever the source stream is
FileStream targetStream = File.OpenWrite(filename, FileMode.Create());
int bytesRead = 0;
byte[] buffer = new byte[2048];
while (true) {
bytesRead = sourceStream.Read(buffer, 0, buffer.length);
if (bytesRead == 0)
break;
targetStream.Write(buffer, 0, bytesRead);
}
sourceStream.Close();
targetStream.Close();
not sure, but maybe check this
http://sourceforge.net/projects/itextsharp/
iTextSharp + FileStream = Corrupt PDF file
Another prominent PDF library (which I have used in the past as well) is iTextSharp. You can take a look at this tutorial on how to convert your Stream to PDF then have the user download it.