Asp.net 从Excel读取图片并保存,无法从内存读取图片,Excel组件和相关IIS的配置及解决办法
</pre>目的:Asp.net web页面,读取Excel,(用的office组件),中的图片注意的事项:<p></p><p>只提供部分代码,因为重点是配置。</p><p>1:要想从Excel里读取图片,只能用剪贴板的方面将图片复制到内存然后再保存图片。</p><p>2:剪贴板的使用要引用WinForm</p><p>3: Excel是单线程的方式,所以代码里使用剪贴板也要用单线程的方式,[STAThread]。</p><p>4:在VS2013中调试状态下代码通过,可以将Excel中的图片取出并保存,在IIS下面报错。</p><p>Retrieving the COM class factory for component with CLSID {00024500-0000-0000-C000-000000000046} failed due to the following error: 80080005. </p><p>这个是一般的Excel报错,需要配置Excel组件,解决办法如下:</p><p></p><p> Excel component set up open component services ,ComponentServices->Computers->DCOM Config-> Microsoft Excel Application</p><p>in Launch and Activation Permissionoption(add network service account give local launch and local activationpermission)</p><p>In Access Permission option (addnetwork service account give local access permission)</p><p>In Change Configuration Permissionoption give permission</p><p>(select the interactive user in identity)</p><p><img src="http://img.blog.csdn.net/20150515110853044?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmRkcWZkZHE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="http://img.blog.csdn.net/20150515110953483?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmRkcWZkZHE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="http://img.blog.csdn.net/20150515110911655?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmRkcWZkZHE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="http://img.blog.csdn.net/20150515111004293?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmRkcWZkZHE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="http://img.blog.csdn.net/20150515111012483?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmRkcWZkZHE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="http://img.blog.csdn.net/20150515110930141?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmRkcWZkZHE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></p><p><strong>if you can’t findMicrosoft Excel Application ,please new a folder named desktop</strong>:</p><p>Create the Desktop folder, because Desktop folder seems to be necessary inthe systemprofile folder to open file by Excel</p><p>1).Windows 2008 Server x64 Please create the folder: C:\Windows\SysWOW64\config\systemprofile\Desktop</p><p>2).Windows 2008 Server x86</p><p> Please create this folder: C:\Windows\System32\config\systemprofile\Desktop </p><p>And give account <span style="color:#333333; background:whitesmoke">Network Service write permission</span></p> 5:<strong><span style="font-size:18px; color:#ff0000">最重要的一步是在IIS中网站对应的应用程序池的配置,也是整个项目的核心配置的地方,应用程序池要将Identity选择为LocalSystem.</span></strong><p><strong><span style="font-size:18px; color:#ff0000"> 这一点很关键,选择LocalSystem才能将excel中的图片复制到内存。</span></strong></p><p><img src="http://img.blog.csdn.net/20150515113821385?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmRkcWZkZHE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></p><p></p><p></p><p>WebForm</p><p></p><p></p><p> 页面点击按钮事件:</p><pre code_snippet_id="667270" snippet_file_name="blog_20150515_2_7423722" name="code" class="csharp"> //上传图片数据
protected void btnUploadPic_Click(object sender, EventArgs e) { try { div_result.InnerHtml = "Result area."; if (string.IsNullOrEmpty(fuUploadPic.FileName)) { div_result.InnerHtml = "Please Select A Excel File"; } else { m_UserID = UserInfo.User_ID.Value.ToString(); string ExcelName = fuUploadPic.FileName.Substring(fuUploadPic.FileName.LastIndexOf('.')); if (ExcelName != ".xls" && ExcelName != ".xlsx") { div_result.InnerHtml = "Please Select A Excel File"; return; } //保存上传文件到服务器 m_PictureExcelPath = Server.MapPath(System.Configuration.ConfigurationManager.AppSettings["MboardUploadFilePath"]) + Guid.NewGuid() + ExcelName; fuUploadPic.SaveAs(m_PictureExcelPath); string strSameNameArticleNo = ""; SameNameArticleNo(ref strSameNameArticleNo); m_SameNameArticleNo = strSameNameArticleNo; string IsRelativeOrAbsolute = System.Configuration.ConfigurationManager.AppSettings["IsRelativeOrAbsolute"]; if (IsRelativeOrAbsolute == null || IsRelativeOrAbsolute == "") m_PicPath = System.Configuration.ConfigurationManager.AppSettings["MboardUploadPicturePath_Absolute"]; else if (IsRelativeOrAbsolute == "1") m_PicPath = Server.MapPath(System.Configuration.ConfigurationManager.AppSettings["MboardUploadPicturePath_Relative"]); else if (IsRelativeOrAbsolute == "2") m_PicPath = System.Configuration.ConfigurationManager.AppSettings["MboardUploadPicturePath_Absolute"]; <span style="color:#ff0000;"> //提取Excel中图片存放到服务器指定路径 <strong><span style="font-size:18px;"> System.Threading.Thread cbThread = new System.Threading.Thread(new System.Threading.ThreadStart(UploadPicture)); cbThread.TrySetApartmentState(System.Threading.ApartmentState.STA);//指定单线程,否则无法从剪贴板中读取数据 cbThread.IsBackground = true; cbThread.Start(); while(cbThread.IsAlive) { System.Threading.Thread.Sleep(1000); }</span></strong></span> } } catch (Exception ex) { WriteErrorLog(ex); div_result.InnerHtml = ex.Message; } finally { //killExcel(); } }
单线程中的方法:
public void UploadPicture() { try { //初始化excel对象 Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application(); Microsoft.Office.Interop.Excel.Workbook workbook = null; try { string sql = ""; //打开xls文件(注意:后面的参数都用Type.Missing填充,表示使用参数的默认值) workbook = excel.Workbooks.Open(m_PictureExcelPath, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing); if (workbook.Worksheets.Count > 0) { for (int i = 1; i <= workbook.Worksheets.Count; i++)//循环取所有的Sheet. { Microsoft.Office.Interop.Excel.Worksheet sheet = workbook.Worksheets.get_Item(i) as Microsoft.Office.Interop.Excel.Worksheet;//从1开始. string ArticleNoAll = ""; string ExcelArticleNoAll = ""; for (int row = 2; row <= sheet.UsedRange.Rows.Count; row++) { //选定图片名称到第n行第2列所在的单元格 string Article_No = ((Microsoft.Office.Interop.Excel.Range)sheet.Cells[row, 2]).Text.ToString().Trim().Replace(" ",""); if (Article_No.Length > 0) { ExcelArticleNoAll += "," + Article_No; string temExcelArticleNoAll = ExcelArticleNoAll + ","; string temExcelArticleNo = "," + Article_No + ","; int a = temExcelArticleNoAll.IndexOf(temExcelArticleNo); int b = temExcelArticleNoAll.LastIndexOf(temExcelArticleNo); if (temExcelArticleNoAll.IndexOf(temExcelArticleNo) == temExcelArticleNoAll.LastIndexOf(temExcelArticleNo)) { if (m_SameNameArticleNo.Contains(temExcelArticleNo) == false || (m_SameNameArticleNo.Contains(temExcelArticleNo) == true && cbReplaceSameName.Checked == true)) { //选定图片到第n行第1列所在的单元格 Microsoft.Office.Interop.Excel.Range r = (Microsoft.Office.Interop.Excel.Range)sheet.Cells[row, 1]; r.Select(); System.Windows.Forms.Clipboard.Clear(); //将单元格复制到剪贴板中 r.CopyPicture(Microsoft.Office.Interop.Excel.XlPictureAppearance.xlScreen, Microsoft.Office.Interop.Excel.XlCopyPictureFormat.xlBitmap); //string[] arrStr = System.Windows.Forms.Clipboard.GetDataObject().GetFormats(); System.Drawing.Image image = System.Windows.Forms.Clipboard.GetImage(); //判断剪贴板中是否存在图片,如果存在,则将图片存到指定目录中 //if (System.Windows.Forms.Clipboard.GetDataObject.ContainsImage()) if (image != null) { ArticleNoAll += ",'" + Article_No + "'"; string picPath = m_PicPath + Article_No + ".png"; image.Save(picPath, System.Drawing.Imaging.ImageFormat.Png);//保存到本地 int pic_height = image.Height; int pic_width = image.Width; sql += "INSERT INTO RMA_R_MBOARD_ARTICLE_PICTURE(Article_No,Picture_Path,OPERATE_USER,UPDATE_TIME,pic_height,pic_width) VALUES('" + Article_No + "','" + picPath + "'," + m_UserID + ",GETDATE()," + pic_height + "," + pic_width + ")" + "\n"; } } } } } if (ArticleNoAll != "" && ArticleNoAll.Length > 1) { ArticleNoAll = ArticleNoAll.Substring(1); sql = "DELETE FROM RMA_R_MBOARD_ARTICLE_PICTURE WHERE Article_No IN (" + ArticleNoAll + ")\n" + sql; int SecRowCount = sqlHelp.ExecuteNonQueryCmd(sql); if (SecRowCount > 0) { div_result.InnerHtml = "Upload Picture Successfully"; return; } else { div_result.InnerHtml = "Upload Picture Failed"; return; } //div_result.InnerHtml = "Upload Picture Successfully"; //return; } else { div_result.InnerHtml = "The picture already exists"; return; } } } else { div_result.InnerHtml = "Excel No Have Picture"; } workbook.Close(false, null, null); excel.Quit(); } catch (Exception ex) { workbook.Close(false, null, null); excel.Quit(); //WriteErrorLog(ex); div_result.InnerHtml = ex.Message; } finally { //System.Runtime.InteropServices.Marshal.ReleaseComObject(mysheet); //mysheet = null; //System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); //workbook = null; //System.Runtime.InteropServices.Marshal.ReleaseComObject(myBooks); //myBooks = null; //System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); //excel = null; workbook.Close(false, null, null); excel.Quit(); //KillExcelThread(excel); } } catch(Exception ex) { WriteErrorLog(ex); div_result.InnerHtml = ex.Message; } }
private void killExcel() { //outPutEXCEL(); GC.Collect(); GC.WaitForPendingFinalizers(); } //获取句柄所对应的线程PID [System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)] private static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID); //Kill Excel 进程 private void KillExcelThread(Microsoft.Office.Interop.Excel.Application excel) { try { IntPtr t = new IntPtr(excel.Hwnd);//得到这个句柄,具体作用是得到这块内存入口 int k = 0; GetWindowThreadProcessId(t, out k);//得到唯一标志k System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k);//k的引用 p.Kill();//关闭k } catch(Exception ex) { WriteErrorLog(ex); div_result.InnerHtml = ex.Message; } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。