web编辑器远程图片自动上传

来源:http://www.w3dev.cn/article/20101216/web-html-editor-remote-images-auto-upload.aspx

  有些时候在使用web编辑器编辑文章的时候,如果有图片,而又不希望从别人的服务器下载图片,这时如果图片比较多,那么一张张保存后重新上传到服务器就会很麻烦。而且有些时候别人的图片是通过动态页面加载,加了防盗链时,粘贴到自己的网站就会显示防盗链的图片。
  今天自己鼓捣了下,弄了一个远程图片自动上传到服务器的ajax+ashx下载远程图片的程序,发现即使是加了防盗链的动态页面加载的图片也能下载原图下来【QQ空间的测试通过,其他的暂时不知道】,省心了很多。
  原理如下
  1)ajax方面:用document.getElementsByTagName获取到img标签,然后判断src是否为远程图片,如果是则搜集图片的url地址,并且保存这些远程图片的img对象到一个数组中,用ajax发送这些远程地址到服务器的动态页,然后处理完毕后返回本地的图片路径,方便更新img的src为自己服务器的url地址。
  2)动态页方面,使用C#的ashx文件下载图片。考虑到了防盗链的动态页加载图片的问题,所以不能通过判断url的后缀是否为图片文件这种方法,也就不好使用webclient直接下载文件。而是使用httpwebrequest来请求图片url【包括防盗链的地址】,然后通过httpwebresponse的ContentType来或者实际图片文件的后缀。

  实现代码如下,可能和实际的应用有些差别,在使用时自己修改下。
  ajax+js代码
  var imgs =document.getElementById('ifrEditor').contentWindow.document.getElementsByTagName('img')//这里注意修改为你自己的web编辑器的ID , upimgs = []//收集远程图片对象img的数组,方便更新src属性 , url = []//收集远程图片地址的数组 , rx = new RegExp('^https?://' + location.host.replace(//./g, '//.'), 'i')//本站主域名的正则 , rxRemote = /^https?:/ //远程图片正则 , xhr, src; for (var i = 0; i < imgs.length; i++) { src = imgs[i].src; if (!rx.test(src) && rxRemote.test(src)) { url[url.length] = src; upimgs[upimgs.length] = imgs[i]; }//收集远程图片地址和img对象 } //获取图片的父对象是否为链接,是则返回以便同时更新链接url function getParantA(obj) { while (obj = obj.parentNode) if (obj.tagName == 'A') return obj; return false; } if (url.length > 0) {//存在远程图片 xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('microsoft.xmlhttp'); xhr.open('POST', 'remotefiles.ashx', true);//==============这里注意修改ajax请求的页面 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); xhr.send('files=' + encodeURIComponent(url.join('|')));//发送远程图片路径 xhr.onreadystatechange = function () { if (xhr.readyState == 4) { var r = 200 == xhr.status ? eval('(' + xhr.responseText + ')') : { success: false, err: 404 == xhr.status ? '请求的页面找不到!' : '发生错误,请稍后再试!' }; if (r.success) {//注意ashx返回的items数组对象一定要和发送时的upimgs数组的长度一致 var pNode; for (var i = 0; i < r.items.length; i++) if (r.items[i]) { upimgs[i].src = '/imgblog/' + r.items[i]; pNode = getParantA(upimgs[i]);//========看图片是否加了链接,加了同时更新链接的href if (pNode) pNode.href = '/imgblog/' + r.items[i]; } } else alert(r.err); } } } else alert('没有远程图片需要上传!');

ashx源代码
using System; using System.Web; using System.IO; using System.Net; public class remotefiles : IHttpHandler, System.Web.SessionState.IRequiresSessionState { /// /// 通过mime类型获取图片后缀 /// /// mime类型 /// 图片后缀 private string GetExt(string MIME) { switch (MIME.ToLower().Trim()) { case "image/gif": return "gif"; case "image/jpeg": return "jpg"; case "image/png": return "png"; case "application/x-ms-bmp": case "image/nbmp": return "bmp"; default: return null; } } /// /// 将下载的文件流写入硬盘 /// /// 本地文件的路径 /// 文件流 private void WriteToHDD(string FullPath,Stream ns) { FileStream writer = new FileStream(FullPath, FileMode.OpenOrCreate, FileAccess.Write); int bufferSize = 512, readSize = 0; byte[] buffer = new byte[bufferSize]; readSize = ns.Read(buffer, 0, bufferSize); while (readSize > 0) { writer.Write(buffer, 0, readSize); readSize = ns.Read(buffer, 0, bufferSize); } writer.Flush(); writer.Close(); } /// /// 下载网络图片 /// /// 图片网络地址 /// 保存到本地图片的时间文件夹 /// 第几个文件 /// 上下文对象 /// 如果是图片则下载并返回生成的文件名,否则返回null private string DownLoadFile(string url,string folder,int i,HttpContext context) { HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url); HttpWebResponse response = (HttpWebResponse)req.GetResponse(); string ext = GetExt(response.ContentType)/*根据响应头获取后缀*/, fileName = null; if (ext != null)//是图片文件 { fileName = DateTime.Now.ToString("yyyyMMddHHmmss")+ i.ToString() + "." + ext; Stream ns = response.GetResponseStream(); WriteToHDD(context.Server.MapPath("~/imgblog/" + folder + "/" + fileName), ns);//注意修改保存图片的路径 ns.Close(); } response.Close(); return fileName; } public void ProcessRequest(HttpContext context) { string js = ""; string files = context.Request.Form["files"]; if (string.IsNullOrEmpty(files)) js = "{success:false,err:'没有远程图片需要上传!'}"; else { string[] arrFiles = files.Split('|'); string func = context.Request.QueryString["func"], folder = DateTime.Now.ToString("yyyyMMdd") , fns = context.Session["fns"] as string, fileName = ""; if (!Directory.Exists(context.Server.MapPath("~/imgblog/" + folder))) Directory.CreateDirectory(context.Server.MapPath("~/imgblog/" + folder)); for (int i = 0; i < arrFiles.Length; i++) { try { fileName = DownLoadFile(arrFiles[i], folder, i, context); if (fileName == null) js += ",false"; else { if (fns == null) fns = folder + "/" + fileName; else fns += "," + folder + "/" + fileName; js += ",'" + folder + "/" + fileName + "'"; } } catch { js += ",false"; } } if (fns != null) context.Session["fns"] = fns;//保存下载的图片的路径到session中,以便存储到文章的表中,这样在删除文章的时候知道要同时删除那些图片 js = "{success:true,items:[" + js.Trim(',') + "]}"; } context.Response.Charset = "utf-8"; context.Response.Write(js); } public bool IsReusable { get { return false; } } }

你可能感兴趣的:(javascript/ajax,Asp.Net/C#)