Multi file upload issue - asp.net

I used multi file upload to upload file in ASP.Net without issues. But now i want to add more functionality like creating thumbnails while uploading below is my code:
try
{
string _path = "~/photos/realimg/";
string _thumPath = "~/photos/thumbimg/";
// Get the HttpFileCollection
HttpFileCollection hfc = Request.Files;
for (int i = 0; i < hfc.Count; i++)
{
HttpPostedFile hpf = hfc[i];
if (hpf.ContentLength > 0)
{
_path += System.IO.Path.GetFileName(hpf.FileName);
_thumPath += System.IO.Path.GetFileName(hpf.FileName.Insert(0, "thumb_"));
hpf.SaveAs(Server.MapPath(_path));
SavePicPath(_path);
System.Drawing.Image realImg = System.Drawing.Image.FromFile(Server.MapPath(_path));
Int32 rH = realImg.Height;
Int32 rW = realImg.Width;
Int32 fW = 170;
Int32 fH = (Int32)Math.Floor((double)rH * (fW / rW));
System.Drawing.Image thumbimg = realImg.GetThumbnailImage(fW, fH, null, IntPtr.Zero);
thumbimg.Save(Server.MapPath(_thumPath));
SavePicPath(_thumPath);
}
}
}
catch
{
}
Anytime it gets to GetThumbnailImage i get an error "Out of memory" please any correction or what am i doing wrong

Change int values to (float or double). i think here fw/rw returning int value than float or double value.

Related

FileStream Object taking forever to push file to browser

I'm using a filestream object to push a report in excel format from our DB, and it works fine for reports that are reasonable in terms the number of rows, however there's one report that has over 15K rows and the site times out after 20 minutes - I know I could increase the timeout, but even 20 minutes is unaccaptable right now. Is there any way to speed things up? Here is my current code:
string path = Server.MapPath(#"~\");
string sourceName = Path.Combine(path, "Demo", "Report_Template", templateName);
string newFileName = Path.Combine(Global.demo_data_directory, #"Reports", #"Demo Download Activity Report.xlsx"); // Path.Combine(path, "Demo_Data", "Reports", Filename + ".xlsx");
string copyresults = Utilities.CopyFile(sourceName, newFileName);
if (copyresults != "Copied file")
{
DemoDAL.ErrorLog("GenerateDownloadActivityReportFile.Page_Load: Copy Error - " + copyresults);
}
else
{
document = SpreadsheetDocument.Open(newFileName, true);
wbPart = document.WorkbookPart;
DataTable datatbl = (DataTable)Session["gvPOC"];
CreateReport(datatbl);
// ADDED THIS *********************************************************************************************************
//wbPart.Workbook.Save();
using (FileStream fsSource = new FileStream(newFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 10240))
{
// Read the source file into a byte array.
byte[] bytes = new byte[fsSource.Length];
int numBytesToRead = (int)fsSource.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
// Read may return anything from 0 to numBytesToRead.
int n = fsSource.Read(bytes, numBytesRead, numBytesToRead);
// Break when the end of the file is reached.
if (n == 0)
break;
numBytesRead += n;
numBytesToRead -= n;
}
numBytesToRead = bytes.Length;
StreamFileToBrowser(newFileName, bytes);
}
File.Delete(newFileName);
}
public void StreamFileToBrowser(string sfilename, byte[] fileBytes)
{
try
{
Response.Clear();
Response.ClearHeaders();
Response.AppendHeader("Content-disposition", String.Format("attachment; filename=\"{0}\"", System.IO.Path.GetFileName(sfilename)));
Response.AppendHeader("Content-Type", "binary/octet-stream");
Response.AppendHeader("Content-length", fileBytes.Length.ToString());
Response.BinaryWrite(fileBytes);
if (Response.IsClientConnected)
Response.Flush();
}
catch (Exception ex)
{
DemoDAL.ErrorLog("StreamFileToBrowser: " + ex.Message);
}
}

Filebytes for multiple fileuploads

I have a form with a multiple fileupload on. (You can select multiple files within the same filecontrol
These files I have to upload to an API
If I don't have a multiple, but a single fileupload, I can do
byte[] filedata = FileUploadControl.FileBytes;
String filestring = Convert.ToBase64String(filedata);
If have multiple fileupload, I can use this to iterate over the files:
HttpFileCollection fileCollection = Request.Files;
for (int i = 0; i < fileCollection.Count; i++)
{
HttpPostedFile uploadfile = fileCollection[i];
if (uploadfile.ContentLength > 0)
{
Int32 ContentLength = uploadfile.ContentLength;
String ContentType = uploadfile.ContentType;
string filename = uploadfile.FileName;
}
}
But I don't have uploadfile.FileBytes
How can I get the contents of the file to a string?
I got it to work like this:
HttpFileCollection fileCollection = Request.Files;
for (int i = 0; i < fileCollection.Count; i++)
{
HttpPostedFile uploadfile = fileCollection[i];
if (uploadfile.ContentLength > 0)
{
...
MemoryStream ms = new MemoryStream(uploadfile.ContentLength);
uploadfile.InputStream.CopyTo(ms);
String filestring = Convert.ToBase64String(ms.ToArray());
...
}
}

Converting HttpFileCollection to byte and stream the data to Image Control in asp.net

HttpFileCollection oHttpFileCollection = e.PostedFiles;
HttpPostedFile oHttpPostedFile = null;
if (e.HasFiles)
{
for (int n = 0; n < e.Count; n++)
{
oHttpPostedFile = oHttpFileCollection[n];
if (oHttpPostedFile.ContentLength <= 0)
continue;
else
oHttpPostedFile.SaveAs(Server.MapPath("Files") + "\\" + System.IO.Path.GetFileName(oHttpPostedFile.FileName));
}
How can I convert HttpFileCollection to byte and read the stream and then display the image to Image Control in asp.net
Thanks
HttpFileCollection oHttpFileCollection = e.PostedFiles;
HttpPostedFile oHttpPostedFile = null;
if (e.HasFiles)
{
for (int n = 0; n < e.Count; n++)
{
oHttpPostedFile = oHttpFileCollection[n];
if (oHttpPostedFile.ContentLength <= 0)
{
continue;
}
else
{
var filename = Path.GetFileName(oHttpPostedFile.FileName);
var path = Path.Combine(Server.MapPath("~/Files/"), filename);
oHttpPostedFile.SaveAs(path);
// Now you could display each image in a dynamically added Image
// control to the page:
Image image = new Image();
image.ImageUrl = "~/Files/" + filename;
// I assume that you have a reference to the current page
// so that you could append image controls to it.
// You could also append the images to a placeholder or a Panel
// on your WebForm
this.Controls.Add(image);
}
}

Web Application not able to Delete files for Read/Write Enabled Folders in ASP.NET

When I'm trying to delete the images uploaded by me via website named "SampleApplication" I can see the following error shown in Stack Trace
The process cannot access the file 'D:\Hosting\123456\html\App_Images\myfolder1\eKuK2511.png' because it is being used by another process.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IO.IOException: The process cannot access the file 'D:\Hosting\123456\html\App_Images\myfolder1\eKuK2511.png' because it is being used by another process.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[IOException: The process cannot access the file 'D:\Hosting\123456\html\App_Images\myfolder1\eKuK2511.png' because it is being used by another process.]
System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) +9723350
System.IO.File.Delete(String path) +9545728
SampleApplication.BasePage.DeleteApp_ImagesById(DataTable dt) +503
SampleApplication.PostLease.MyAccount.DeleteAd_Property(Object sender, EventArgs e) +193
System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e) +118
System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +113
System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +9
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +176
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272
The folder App_Images has been given Read/write Permission and inherits to child folders namely myfolder1, myfolder2, myfolder3, myfolder4. Even when I tried to forcefully delete the image eKuK2511.png from the FTP File manager it is showing the following error:
550 The process cannot access the file because it is being used by another process.
How to getrid of this error?
Edit:
Upload Code:
public void UploadImages()
{
if (ServerSideValidation() == true)
{
string SavePath;
ImgPaths = new List<string>();
// Get the HttpFileCollection
HttpFileCollection hfc = Request.Files;
if (hfc.Count > 0)
{
for (int i = 0; i < hfc.Count; i++)
{
HttpPostedFile hpf = hfc[i];
if (hpf.ContentLength > 0)
{
#region trials compression.
SavePath = "~/App_Images/" + Session["AppContext"].ToString() + "/" + GetUniqueKey() + GetFileExtension(hpf.FileName);
SaveImageByCompressing(hpf, SavePath);
#endregion
//SavePath can be saved in DB.
ImgPaths.Add(SavePath);
//Save Thumbnail Image.
if (i == 0)
{
string savedName = "Thumb_" + GetUniqueKey() + GetFileExtension(AppDomain.CurrentDomain.BaseDirectory + ImgPaths[0].ToString().Replace("~/", "\\").Replace("/", "\\"));
SavePath = "~/App_Images/" + Session["AppContext"].ToString() + "/" + savedName;
SaveThumbImage(AppDomain.CurrentDomain.BaseDirectory + ImgPaths[0].ToString().Replace("~/", "").Replace("/", "\\"), AppDomain.CurrentDomain.BaseDirectory + "App_Images\\" + Session["AppContext"].ToString() + "\\" + savedName, 75, 75);
ImgPaths.Add(SavePath);
}
}
}
Session.Remove("AppContext");
lblMsg.Text = "Images Uploaded Successfully.";
//ShowUploadedImages(ImgPaths);
}
else
{
lblMsg.Text = "Images uploaded are either in wrong format or were deleted after uploading.";
}
}
else
{
lstPaths = new List<string>();
lblMsg.Text = "No Images Uploaded";
}
}
private void SaveImageByCompressing(HttpPostedFile hpf, string filePath)
{
Image imgFromClient = Image.FromStream(hpf.InputStream);
string SavetoFullPath = AppDomain.CurrentDomain.BaseDirectory + filePath.Replace("~/", "").Replace("/", "\\");
Image.GetThumbnailImageAbort myCallbackCompressed = new Image.GetThumbnailImageAbort(ThumbnailCallback);
Image imageToSave= imgFromClient.GetThumbnailImage(imgFromClient.Width, imgFromClient.Height, myCallbackCompressed, IntPtr.Zero);
imageToSave.Save(SavetoFullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
public static void SaveThumbImage(string imagePath, string filePath, int width = 0, int height = 0)
{
Image originalImage = Image.FromFile(imagePath);
if (width > 0 && height > 0)
{
Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);
Image imageToSave = originalImage.GetThumbnailImage(width, height, myCallback, IntPtr.Zero);
imageToSave.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
else
{
originalImage.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
private static bool ThumbnailCallback() { return false; }
private bool ServerSideValidation()
{
string errorMsg = string.Empty, temp = null;
bool errorFlag = true;
// Get the HttpFileCollection
HttpFileCollection hfc = Request.Files;
for (int i = 0; i < hfc.Count; i++)
{
HttpPostedFile hpf = hfc[i];
if (hpf.ContentLength > 0 && hpf.FileName!=String.Empty)
{
temp = ValidateImage(hpf);
if (temp != null)
{
errorMsg += GetFileName(hpf.FileName.ToString()) + " has error : " + temp;
temp = null;
}
}
else
{
return false;
}
}
if (!string.IsNullOrWhiteSpace(errorMsg))
{
lblMsg.Text = errorMsg;
errorFlag = false;
}
return errorFlag;
}
private string GetFileExtension(string filePath)
{
FileInfo fi = new FileInfo(filePath);
return fi.Extension;
}
private string GetFileName(string filePath)
{
FileInfo fi = new FileInfo(filePath);
return fi.Name;
}
private string GetUniqueKey()
{
int maxSize = 8;
char[] chars = new char[62];
string a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
chars = a.ToCharArray();
int size = maxSize;
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data);
size = maxSize;
data = new byte[size];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(size);
foreach (byte b in data)
{
result.Append(chars[b % (chars.Length - 1)]);
}
return Session["AppContext"].ToString() + Page.User.Identity.Name.ToString() + result.ToString();
}
private string ValidateImage(HttpPostedFile myFile)
{
string msg = null;
//6MB
int FileMaxSize = 6291456;
//Check Length of File is Valid or Not.
if (myFile.ContentLength > FileMaxSize)
{
msg = msg + "File Size is Too Large. You are allowed only a maximum of 6MB per Image.";
}
//Check File Type is Valid or Not.
if (!IsValidFile(myFile.FileName))
{
msg = msg + "Invalid File Type.";
}
return msg;
}
private bool IsValidFile(string filePath)
{
bool isValid = false;
string[] fileExtensions = { ".BMP", ".JPG", ".PNG", ".GIF", ".JPEG" };
for (int i = 0; i < fileExtensions.Length; i++)
{
if (filePath.ToUpper().Contains(fileExtensions[i]))
{
isValid = true; break;
}
}
return isValid;
}
Delete Code:
/// <summary>
/// Delete all images. If there are no Images then by default NoImage.png is assigned. So skip deleting that image.
/// </summary>
/// <param name="dt"></param>
protected void DeleteApp_ImagesById(DataTable dt)
{
if (dt.Rows[0][0].ToString() != "~/images/NoImage.png")
{
for (int i = 0; i < dt.Columns.Count; i++)
{
if (dt.Rows[0][i].ToString() != string.Empty)
{
string str = Regex.Replace(dt.Rows[0][i].ToString(), "~/", "");
File.Delete(Request.PhysicalApplicationPath.ToString() + Regex.Replace(str, "/", "\\").ToString());
}
}
}
}
The docs on MSDN about Image.Save say that the file remains locked until the Image is disposed.
So I suppose that changing the code that save the images in this way
private void SaveImageByCompressing(HttpPostedFile hpf, string filePath)
{
using(Image imgFromClient = Image.FromStream(hpf.InputStream))
{
string SavetoFullPath = AppDomain.CurrentDomain.BaseDirectory +
filePath.Replace("~/", "").Replace("/", "\\");
Image.GetThumbnailImageAbort myCallbackCompressed =
new Image.GetThumbnailImageAbort(ThumbnailCallback);
using(Image imageToSave= imgFromClient.GetThumbnailImage(imgFromClient.Width,
imgFromClient.Height, myCallbackCompressed, IntPtr.Zero))
{
imageToSave.Save(SavetoFullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
public static void SaveThumbImage(string imagePath, string filePath,
int width = 0, int height = 0)
{
using(Image originalImage = Image.FromFile(imagePath))
{
if (width > 0 && height > 0)
{
Image.GetThumbnailImageAbort myCallback =
new Image.GetThumbnailImageAbort(ThumbnailCallback);
using(Image imageToSave = originalImage.GetThumbnailImage(width, height,
myCallback, IntPtr.Zero))
{
imageToSave.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
else
{
originalImage.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
is a safe way to ensure your images are immediately unlocked when you finish with the upload code

Not able to display an image in repeater control for [thumbnail images]

i have imgae path in datatable[id, path] now this would a value like
ex: id path
1 F:\R&D\RD\RD\Images\a1.JPG;
2 F:\R&D\RD\RD\Images\a2.JPG;
3 F:\R&D\RD\RD\Images\a3.JPG;
now these images are in size width*height (1018*768). now i need to convert these images into thumnail
caling the function
**C_Thumbnails(100, "F:\R&D\RD\RD\Images\a1.JPG", "F:\R&D\RD\RD\Images]thum.jpg")**
public static void C_Thumbnails(int size, string FilePath, string ThumbPath)
{
System.Drawing.Image image = System.Drawing.Image.FromFile(FilePath);
try
{
int thumbHeight, thumbWidth;
decimal h = image.Height;
decimal w = image.Width;
if (image.Height > image.Width)
{
thumbHeight = size;
decimal tWidth = (w / h) * thumbHeight;
thumbWidth = Convert.ToInt32(tWidth);
}
else
{
thumbWidth = size;
decimal tHeight = (h / w) * thumbWidth;
thumbHeight = Convert.ToInt32(tHeight);
}
System.Drawing.Image thumbnailImage = image.GetThumbnailImage(thumbWidth, thumbHeight, null, IntPtr.Zero);
image.Dispose();
thumbnailImage.Save(ThumbPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
image.Dispose();
throw ex;
}
}
like this i am coverting into thumbnail image. but here i am saving the thumbnail image under the path F:\R&D\RD\RD\Images\thum.jpg .
so is there any way without saving the thumbnail in the disk and how to bind the new thumbnail image in the repeater control and i need to show image there. but if once user clicks on the thumnail image a orignal image should pop up.
if any one have did this functionlity any where let me know
working on this solution from past 2 days.
any help would be greatly appreciated
now after changing code
like this
public void ProcessRequest(HttpContext context)
{
string imageid = context.Request.Params["ImageID"];
string thumbnail = context.Request.Params["thumbnail"];
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString);
connection.Open();
SqlCommand command = new SqlCommand("select Image from Image where ImageID=" + imageid, connection);
SqlDataReader dr = command.ExecuteReader();
dr.Read();
string filePath = dr["image"].ToString();
dr.Close();
if (!System.IO.File.Exists(filePath))
{
//you have a problem
return;
}
if (context.Request.Params["thumbnail"] == "true")
{
//TODO: the thumbnail
// Image thumbnailImage = originalImage.GetThumbnailImage to generate thumbnail then
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "image/" + format;
thumbnailImage.Save(Response.OutputStream, imageFormat);
thumbnailImage.Dispose();
}
else
{ //stream directly the image fromdisk
System.IO.FileStream fs = System.IO.File.OpenRead(filepath);
const int ChunkSize = 10000;
Byte[] buffer = new Byte[ChunkSize];
long dataLengthToRead = fs.Length;
while (dataLengthToRead > 0)
{
int lengthRead = fs.Read(buffer, 0, ChunkSize);
Response.OutputStream.Write(buffer, 0, lengthRead);
System.Web.HttpContext.Current.Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
fs.Close();
}
}
}
in repeater control i have added this line of code
','_blank','toolbar=no,menubar=no'))" > '/>
my thumbnail image is not displayed still but once i click my thumbnail image i am able to see the entire image in new pop up
You should use a Photo Image Handler to serve the pages from your disk to the clients.
Then in the repeater control
<a href="ImageHandler.ashx?thumbnail=false&id='<%# Eval("ID")%>'>
<img src="ImageHandler.ashx?thumbnail=true&id='<%# Eval("ID")%>' border='0'/>
</a>
The ideea is not to pass in the actual path/name of the file, but the ID of the item you wish to view. Then the handler will:
public void ProcessRequest(System.Web.HttpContext context)
{
string filePath = //TODO: Get File Path from ItemID = context.Request.Params["id"]
if (!System.IO.File.Exists(filePath))
{
//you have a problem
return;
}
if(context.Request.Params["thumbnail"]=="true")
{
//TODO: the thumbnail
// Image thumbnailImage = originalImage.GetThumbnailImage to generate thumbnail then
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "image/" + format;
thumbnailImage.Save(Response.OutputStream, imageFormat);
thumbnailImage.Dispose();
} else
{ //stream directly the image fromdisk
System.IO.FileStream fs = System.IO.File.OpenRead(filepath);
const int ChunkSize = 10000;
Byte[] buffer = new Byte[ChunkSize];
long dataLengthToRead = fs.Length;
while (dataLengthToRead > 0)
{
int lengthRead = fs.Read(buffer, 0, ChunkSize);
Response.OutputStream.Write(buffer, 0, lengthRead);
System.Web.HttpContext.Current.Response.Flush();
dataLengthToRead = dataLengthToRead - lengthRead;
}
fs.Close();
}
}

Resources