Valums uploader and DB save on multiple files - c#

I am using valums uploader with an ashx file example that I found & tweeked, and want to save data from each file to the db when I upload, stepping through the code , there doesn't seem any way to differentiate which file is uploaded in which order , watching certain variable , the code jumps all over the place. It works fine for single files but more than 1 is an issue. Also, context.Request.Files.Count is always 0
byte[] buffer = new byte[request.ContentLength];
fileName = request.RawUrl.Split('=')[1];
fmt = Path.GetExtension(fileName);
using (BinaryReader br = new BinaryReader(request.InputStream))
br.Read(buffer, 0, buffer.Length);
File.WriteAllBytes(StorageRoot + request["qqfile"], buffer);
success = false;
context.Response.Write("{success:true}");
HttpContext.Current.ApplicationInstance.CompleteRequest();
Any ideas?

I've used valums uploader without problem. Different browsers upload files in different ways. IE will use an file upload html control, whilst Firefox & Chrome can do it Ajax style. I wrote my own upload handler, but the first thing you need to do is figure which method was used.
I do this like this:
if (HttpContext.Current.Request.QueryString["qqfile"] != null)
file = new UploadedFileXhr();
else if (HttpContext.Current.Request.Files.Count > 0)
file = new UploadedFileForm();
else
return new UploadResult("Request was not valid.");
An XHR upload means you read from the input buffer like so:
int read = HttpContext.Current.Request.InputStream.Read(buffer, 0, buffer.Length);
while (read == buffer.Length)
{
ms.Write(buffer, 0, buffer.Length);
read = HttpContext.Current.Request.InputStream.Read(buffer, 0, buffer.Length);
}
ms.Write(buffer, 0, read);
A file upload is simpler like so:
UploadResult result = new UploadResult(true);
result.Stream = _File.InputStream;
result.Name = System.IO.Path.GetFileName(_File.FileName);
Even if you add multiple files in the client, each file is uploaded individually.

Related

Image loss quality after upload via HttpPostedFile.SaveAs(imgPath)

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.

How to retrieve .dotx and .csv files from Resources Folder in C#?

I have an application that uses a template file and a CSV file. It works perfectly fine since I do have the said files on my computer and I am referencing their paths. The only thing I want to do is that when the software is published and installed (and the said files are in the Resources folder so it would make them an embedded resource), the csv and template files would be copied to a directory folder that my program would use. Preferably the paths it would be copied to would be something like this : "C:\FILES" + template.dotx .
Now how do I get/retrieve the said files from the Resources Folder in my software into a new folder?
You could call
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
And inspect which embedded resources are accessible. Then you can compare that against what you are passing in to see if you are indeed accomplishing what you expected to.
string FileExtractTo = "C:\FILES";
DirectoryInfo dirInfo = new DirectoryInfo(FileExtractTo);
if (!dirInfo.Exists())
dirInfo.Create();
using (Stream input = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
using (Stream output = File.Create(FileExtractTo + "\template.dotx"))
{
CopyStream(input, output);
}
CopyStream Method:
public static void CopyStream(Stream input, Stream output)
{
// Insert null checking here for production
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}

File upload with c# and streaming

Looking at the different ways to upload a file in .NET, e.g. HttpPostedFile, and using a HttpHandler, I'm trying to understand how the process works in a bit more details.
Specifically how it writes the information to a file.
Say I have the following:
HttpPostedFile file = context.Request.Files[0];
file.SaveAs("c:\temp\file.zip");
The actual file does not get created until the full stream seems to be processed.
Similarly:
using (Stream output = File.OpenWrite("c:\temp\file.zip"))
using (Stream input = file.InputStream)
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
I would have thought that this would "progressively" write the file as it reads the stream. Looking at the filesystem, it does not seems to do this at all. If I breakpoint inside the while, it does though.
What I'm trying to do, is have it so you upload a file (using a javascript uploader), and poll alongside, whereby the polling ajax request tries to get the fileinfo(file size) of the uploaded file every second. However, it always returns 0 until the upload is complete.
Vimeo seems to be able to do this type of functionality (for IE)?? Is this a .NET limitation, or is there a way to progressively write the file from the stream?
Two points:
First, in Windows, the displayed size of a file is not updated constantly. The file might indeed be growing continually, but the size only increases once.
Second (more likely in this case), the stream might not be flushing to the disk. You could force it to by adding output.Flush() after the call to output.Write(). You might not want to do that, though, since it will probably have a negative impact on performance.
Perhaps you could poll the Length property of the output stream directly, instead of going through the file system.
EDIT:
To make the Length property of the stream accessible to other threads, you could have a field in your class and update it with each read/write:
private long _uploadedByteCount;
void SomeMethod()
{
using (Stream output = File.OpenWrite("c:\temp\file.zip"))
using (Stream input = file.InputStream)
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
Interlocked.Add(ref _uploadedByteCount, bytesRead);
}
}
}
public long GetUploadedByteCount()
{
return _uploadedByteCount;
}

How to save FileSteam as PDF file

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.

File upload progress bar in ASP.NET 2.0

I have a file upload on my .NET website. I used the FileUpload .NET control for the upload, and set the target of the form to a hidden iframe. I use client-side script to submit the form, then display a progress bar on the page, which does an AJAX request to an ashx file on the same server and updates the progress bar every second.
Here's the part of the code for when the file is uploading -
string fileString = StringGenerator.GenerateString(8);
System.IO.Stream fileStream = System.IO.File.Create(fileRoot+ fileString + ".mp3");
System.IO.Stream inputStream = fileUpload.PostedFile.InputStream;
byte[] buffer = new byte[256];
int read;
if(StaticProgress.Progress.ContainsKey(trackId)) StaticProgress.Progress[trackId] = 0d;
else StaticProgress.Progress.Add(trackId, 0d);
int totalRead = 0;
long length = inputStream.Length;
while ((read = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
totalRead += read;
fileStream.Write(buffer, 0, read);
StaticProgress.Progress[trackId] = (double)totalRead / (double)length;
}
StaticProgress.Progress is a property which returns a static Dictionary.
Here is the code in the ashx file that gets the progress of the
context.Response.ContentType = "text/javascript";
int id;
if(!int.TryParse(context.Request.QueryString["id"], out id) || !StaticProgress.Progress.ContainsKey(id))
context.Response.Write("{\"error\":\"ID not found\"}");
else
context.Response.Write("{\"id\":\"" + id + "\",\"decimal\":" + StaticProgress.Progress[id] + "}");
Here I always "ID not found" while the file is uploading, but when the file has finished uploading, I get a successful - decimal : 1.
I've tried using session variables before this and got the same result. I've tried using a public static (thread safe?) Dictionary, but I get the same result. Has anyone came across anything like this before? Does the code not execute until the client request has been fully received?
The standard file upload control provides no progress abilities - it does not receive the file until the file has been fully received by the server. By the time you open the stream on the .PostedFile, the file has been completely uploaded.
There are a number of better solutions to uploading discussed here.

Categories