Does anyone know of a way in .NET to take an incoming stream of a file and convert it to an image to be stored in the database? (Not sure if this is possible, but wanted to check).
Edit: it is not necessarily an image stream
You need to read the stream into a byte[], then save that into the database.
You can convert the image stream to byte array and store in binary or varbinary data type in database.
Here is a short example of transferring the image into a byte array in C#:
private static byte[] ReadImage(string p_postedImageFileName, string[] p_fileType)
{
bool isValidFileType = false;
try
{
FileInfo file = new FileInfo(p_postedImageFileName);
foreach (string strExtensionType in p_fileType)
{
if (strExtensionType == file.Extension)
{
isValidFileType = true;
break;
}
}
if (isValidFileType)
{
FileStream fs = new FileStream(p_postedImageFileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] image = br.ReadBytes((int)fs.Length);
br.Close();
fs.Close();
return image;
}
return null;
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
Related
I create an asp.net 4.0 web application which has a web service for uploading images. I am uploading images by sending the image in form of Base64 string from my mobile app to the web service.
Following is my code:
public string Authenticate(string username, string password, string fileID, string imageData)
{
Dictionary<string, string> responseDictionary = new Dictionary<string, string>();
bool isAuthenticated = true; // Set this value based on the authentication logic
try
{
if (isAuthenticated)
{
UploadImage(imageData);
string result = "success";
var message = "Login successful";
responseDictionary["status"] = result;
responseDictionary["message"] = message;
}
}
catch (Exception ex)
{
responseDictionary["status"] = ex.Message;
responseDictionary["message"] = ex.StackTrace;
}
return new JavaScriptSerializer().Serialize(responseDictionary);
}
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)Image.FromStream(ms);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
ms.Close();
bitmap.Save(uploadPath, System.Drawing.Imaging.ImageFormat.Jpeg);
bitmap.Dispose();
}
This code was working fine on my local ASP.NET development server and I was able to see the uploaded image in my "uploads" directory. However, after transferring the code to the FTP directory, I am now getting the following error:
A generic error occurred in GDI+
I have checked that the upload directory has proper permission by creating a dummy .aspx page and creating a text file on page_load, and it works fine.
Even after doing google search, I was not able to solve this problem. Can anybody help me fixing this?
Thanks a lot in advance.
Instead of writing directly to files, save your bitmap to a MemoryStream and then save the contents of the stream to disk. This is an old, known issue and, frankly, I don't remember all the details why this is so.
MemoryStream mOutput = new MemoryStream();
bmp.Save( mOutput, ImageFormat.Png );
byte[] array = mOutput.ToArray();
// do whatever you want with the byte[]
In your case it could be either
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
// store the byte[] directly, without converting to Bitmap first
using ( FileStream fs = File.Create( uploadPath ) )
using ( BinaryWriter bw = new BinaryWriter( fs ) )
bw.Write( imageBytes );
}
or
private void UploadImage(string uploadedImage)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(uploadedImage);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)Image.FromStream(ms);
string uploadPath = Server.MapPath("..\\uploads\\") + DateTime.Now.Ticks.ToString() + ".jpeg";
ms.Close();
// convert to image first and store it to disk
using ( MemoryStream mOutput = new MemoryStream() )
{
bitmap.Save( mOutput, System.Drawing.Imaging.ImageFormat.Jpeg);
using ( FileStream fs = File.Create( uploadPath ) )
using ( BinaryWriter bw = new BinaryWriter( fs ) )
bw.Write( mOutput.ToArray() );
}
}
Furthermore I think it's worth pointing out that when MemoryStream is used, stream must always be closed and save method MUST be called before the stream closure
byte[] byteBuffer = Convert.FromBase64String(Base64String);
MemoryStream memoryStream = new MemoryStream(byteBuffer);
memoryStream.Position = 0;
Bitmap bmpReturn = (Bitmap)Bitmap.FromStream(memoryStream);
bmpReturn.Save(PicPath, ImageFormat.Jpeg);
memoryStream.Close();
I am working with a MS Dynamics Nav Database that have a file attachment tables. The files are stored in MS SQL. I am able to pull the files to my desktop with a custom asp.net application that I have built, but when I open the files, they are corrupted. These are PDFs files that are located in the "image" file type column of the database and I have tried to download over 20 files. All of them varies in size and seem to download successfully.
The reason why I suspect these are PDFs files is because the column right next to the binary columns give me the name of the file as in PDF format. I have also tried to renaming the file after I download to different image formats but without any luck when I tried to open it. This is not my first project to retrieve binary files, from MS SQL database. If anyone work on getting files off the Nav database before, please help me. The sample code below I wrote to retrieve files using LINQ to SQL when I give it a specific ID in the browser. Please advice me if you know any sort of compression or encryption in the binary files itself and how to grab the file successfully to read it. Thanks
protected void getFileFromID(string queryid)
{
string Filename = string.Empty;
byte[] bytes;
try
{
DataClassesFilesDataContext dcontext = new DataClassesFilesDataContext();
var myfile = (from file in dcontext.Comptroller_File_Attachments
where file.No_ == queryid
select file).First();
if (myfile.Table_ID.ToString().Length > 0 && myfile.Attachment != null)
{
Filename = myfile.FileName.ToString();
bytes = myfile.Attachment.ToArray();
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + Filename);
Response.BinaryWrite(bytes);
Response.End();
}
else
{
Response.Write("no file exist");
}
}
catch (Exception e)
{
Response.Write(e);
}
}
Well. I figured it out. I read on a blog that 4 bytes was the "magic number" to get rid off. So all you have to do is get rid of 4 bytes from the BLOB bytes array and then decompress it with DeflateStream. The example code I post below is an example where it takes in a byte array and skip the first 4 using LINQ-to-SQL and return the byte and string filename for the 2nd function. It also pass in a queryid string parameter. I am sure the code can be improve more for efficiency purposes. For those who have trouble with this, just give this a try.
//get bytes and remove first 4 bytes from bytes array
protected Tuple<byte[], string> getBytesfromFile(string queryID)
{
byte[] MyFilebytes = null;
string filename = string.Empty;
try
{
DataClassesFilesDataContext dcontext = new DataClassesFilesDataContext();
var myfile = (from file in dcontext.Comptroller_File_Attachments
where file.No_ == queryID
select file).First();
if (myfile.Table_ID.ToString().Length > 0 && myfile.Attachment != null)
{
MyFilebytes = myfile.Attachment.ToArray().Skip(4).ToArray();
filename = myfile.FileName.ToString();
}
else
Response.Write("no byte to return");
}
catch
{
Response.Write("no byte");
}
return Tuple.Create(MyFilebytes, filename);
}
//after getting the remaining bytes (after removing 4 first byte) deflate the byte and then store it in a memory steam and get the result back.
protected void getFile()
{
try
{
string Filename = string.Empty;
byte[] myfile = getBytesfromFile(getQueryID()).Item1;
byte[] result;
using (Stream input = new DeflateStream(new MemoryStream(myfile),
CompressionMode.Decompress))
{
using (MemoryStream output = new MemoryStream())
{
input.CopyTo(output);
result = output.ToArray();
}
}
Filename = getBytesfromFile(getQueryID()).Item2;
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + Filename);
Response.BinaryWrite(result);
Response.End();
}
catch (Exception e)
{
Response.Write(e);
}
}
//pass in file id
protected string getQueryID()
{
QueryID.QueryStringID = Request.QueryString["fileid"];
return QueryID.QueryStringID;
}
For video's to be copy protected , I thought of
Step-1) encrypting video files with key.
step-2)Decrypting a file OR decrypt in memory stream.
Step-3) Play decrypted file OR Play from Memory stream.
I have succesfully encrypted and decrypted a video file with key. But don't know how to play decrypted file(.dnc file).
Can somebody will please help me to play video file from decrypted (File or Memory Stream).
Code for Decryption
private void Decryption(string filePath)
{
try
{
DateTime current = DateTime.Now;
string encName = filePath + "data" + ".enc";
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
#region Seperate key and data
byte[] alldata = File.ReadAllBytes(filePath);
byte[] getencryptedkey = new byte[128];
byte[] data = new byte[alldata.Length - 128];
for (int i = 0; i < alldata.Length - 128; i++)
{ data[i] = alldata[i]; }
for (int i = alldata.Length - 128, j = 0; i < alldata.Length; i++, j++)
{ getencryptedkey[j] = alldata[i]; }
using (BinaryWriter bw = new BinaryWriter(File.Create(encName)))
{
bw.Write(data);
bw.Close();
}
#endregion
#region key decryption
StreamReader reader = new StreamReader("PublicPrivateKey.xml");
string publicprivatekeyxml = reader.ReadToEnd();
RSA.FromXmlString(publicprivatekeyxml);
reader.Close();
byte[] decryptedKey = RSA.Decrypt(getencryptedkey, false);
pwd = System.Text.ASCIIEncoding.Unicode.GetString(decryptedKey);
byte[] dk = null;
byte[] div = null;
crm.getKeysFromPassword(pwd, out dk, out div);
cryptoKey = dk;
cryptoIV = div;
#endregion
string ext = Path.GetExtension(encName).ToLower();
if (ext != ".enc")
{
MessageBox.Show("Please Enter correct File");
return;
}
string dncName = Path.GetDirectoryName(encName) + "\\" + Path.GetFileNameWithoutExtension(encName);
dncName = current.Date.Day.ToString() + current.Date.Month.ToString() + current.Date.Year.ToString() + current.TimeOfDay.Duration().Hours.ToString() + current.TimeOfDay.Duration().Minutes.ToString() + current.TimeOfDay.Duration().Seconds.ToString() + ".wmv";
try
{
if (crm.DecryptData(encName, dncName, cryptoKey, cryptoIV))
{
FileInfo fi = new FileInfo(encName);
FileInfo fi2 = new FileInfo(dncName);
if ((fi.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{ fi.Attributes &= ~FileAttributes.ReadOnly; }
//copy creation and modification time
fi2.CreationTime = fi.CreationTime;
fi2.LastWriteTime = fi.LastWriteTime;
//delete encrypted file
File.Delete(encName);
MessageBox.Show("File Decrypted");
}
else
{
MessageBox.Show("The file can't be decrypted - probably wrong password");
}
}
catch (CryptographicException ex)
{ MessageBox.Show(ex.Message); }
catch (IOException ex)
{ MessageBox.Show(ex.Message); }
catch (UnauthorizedAccessException ex)
{ //i.e. readonly
MessageBox.Show(ex.Message);
}
}
catch (Exception ex)
{ MessageBox.Show(ex.Message); }
}
To copy-protect a video file, the best way to accomplish it used to be apply DRM to it. That way you can restrict how may times it should play or how long it should be available to the user, but that still could be broken via a lot of means.
You cannot make any video 100% copy protected. Please read the article below. If that was the case, the hollywood movies wouldnt be freely available via the torrent networks.
http://www.streamingmedia.com/Articles/Editorial/Featured-Articles/DRM-Is-Dead-79353.aspx
I am not sure if this is possible so it would be nice to have some help.
What I want to do is use a fileupload control in asp.net to select a csv file. Then use my submit button on the page to run my server side code which will take that csv file and put it into memory stream where it will be parsed and then added to collection object.
I do know it's easier to save the csv file to a physical path and then do some kind of cleanup where I delete the file but if possible I would like to do it this way.
See below for code so far:
protected void btnUpload_Click(object sender, EventArgs e)
{
string connectingString = "";
if (ctrlFileUpload.HasFile)
{
string fileName =
Path.GetFileName(ctrlFileUpload.PostedFile.FileName);
string fileExtension =
Path.GetExtension(ctrlFileUpload.PostedFile.FileName);
ReadCsv(fileName);
}
}
protected void ReadCsv(string fileName)
{
// Some logic for parsing csv file in memory stream
}
}
Any ideas? Thanks!
I know this is an old question, but the below code will work for reading your posted text file into a memory stream using a StreamReader and is compatible with .NET 4.0:
protected void ReadCsv()
{
StreamReader reader = new StreamReader(ctrlFileUpload.PostedFile.InputStream);
string content = reader.ReadToEnd();
}
Note, this method is only efficient if you have enough memory on the server to handle larger files for multiple users concurrently. You don't want to use this approach if you have hundreds of users posting files simultaneously to a memory stream and causing your server to crash due to insufficient available memory. You'll also want to check if this is an acceptable method if you're on a shared hosting environment.
Does this help?
This should give you the stream. So you'd make your ReadCsv method accept a reference to the stream, and pass that to it rather than the filename, and work against the stream.
MSDN FileUpload.FileContent Property
//Try below one to capture data in MemoryStream from FileUpload Control
protected void btnFileUpload_Click(object sender, EventArgs e)
{
if (FileUploadControl.HasFile)
{
try
{
#region Capture file data in Memory Stream
byte[] fileData = null;
Stream fileStream = null;
int length = 0;
length = FileUploadControl.PostedFile.ContentLength;
fileData = new byte[length + 1];
fileStream = FileUploadControl.PostedFile.InputStream;
fileStream.Read(fileData, 0, length);
//Use MemoryStream to capture file data
MemoryStream stream = new MemoryStream(fileData);
Session["FileUploaded"] = stream;
#endregion
StreamReader strFile;
using (strFile = new StreamReader(stream))
{
string line;
DataTable dtStudentData = CreateDataTable();
DataRow drStudentRow;
List<String> errorMessages = new List<String>();
// Read and display lines from the file until the end of the file is reached.
while ((line = strFile.ReadLine()) != null)
{
if (line.Trim().Length > 0)
{
System.Threading.Thread.Sleep(1000);
string[] columns = line.Split('\t'); //splitting the line which was read by the stream reader object
Int32 charpos = (Int32)strFile.GetType().InvokeMember("charPos", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, strFile, null);
Int32 charlen = (Int32)strFile.GetType().InvokeMember("charLen",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.GetField
, null, strFile, null);
int lineno = (Int32)strFile.BaseStream.Position - charlen + charpos;
//Add data row in Data Table
drStudentRow = dtStudentData.NewRow();
// TO DO code - Fill data table
dtStudentData.Rows.Add(drStudentRow);
}
}
strFile.Dispose();
dtStudentData.Rows.RemoveAt(0); //Remove the first column since its the column name not necessary to insert in the database table
PopulateStudentInvalidDataGridView(dtStudentData); // Bind Grid
Session["StudentData_FileParsedStudentRegistrtaionTable"] = dtStudentData;
strFile.Close(); //release the stream reader
}
}
catch (Exception ex)
{
String error = ex.Message;
}
}
}
I'm making a simple download service so a user can download all his images from out site.
To do that i just zip everything to the http stream.
However it seems everything is stored in memory, and the data isn't sent til zip file is complete and the output closed.
I want the service to start sending at once, and not use too much memory.
public void ProcessRequest(HttpContext context)
{
List<string> fileNames = GetFileNames();
context.Response.ContentType = "application/x-zip-compressed";
context.Response.AppendHeader("content-disposition", "attachment; filename=files.zip");
context.Response.ContentEncoding = Encoding.Default;
context.Response.Charset = "";
byte[] buffer = new byte[1024 * 8];
using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipOutput = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(context.Response.OutputStream))
{
foreach (string fileName in fileNames)
{
ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(fileName);
zipOutput.PutNextEntry(zipEntry);
using (var fread = System.IO.File.OpenRead(fileName))
{
ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fread, zipOutput, buffer);
}
}
zipOutput.Finish();
}
context.Response.Flush();
context.Response.End();
}
I can see the the worker process memory growing while it makes the file, and then releases the memory when its done sending. How do i do this without using too much memory?
Disable response buffering with context.Response.BufferOutput = false; and remove the Flush call from the end of your code.
use Response.BufferOutput = false; at start of ProcessRequest and flush response after each file.
FYI. This is working code to recursively add an entire tree of files, with streaming to browser:
string path = #"c:\files";
Response.Clear();
Response.ContentType = "application/zip";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", "hive.zip"));
Response.BufferOutput = false;
byte[] buffer = new byte[1024 * 1024];
using (ZipOutputStream zo = new ZipOutputStream(Response.OutputStream, 1024 * 1024)) {
zo.SetLevel(0);
DirectoryInfo di = new DirectoryInfo(path);
foreach (string file in Directory.GetFiles(di.FullName, "*.*", SearchOption.AllDirectories)) {
string folder = Path.GetDirectoryName(file);
if (folder.Length > di.FullName.Length) {
folder = folder.Substring(di.FullName.Length).Trim('\\') + #"\";
} else {
folder = string.Empty;
}
zo.PutNextEntry(new ZipEntry(folder + Path.GetFileName(file)));
using (FileStream fs = File.OpenRead(file)) {
ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fs, zo, buffer);
}
zo.Flush();
Response.Flush();
}
zo.Finish();
}
Response.Flush();