淘宝开店过程中的技术应用——【线程池】实现【图片下载】
2011-03-16 09:47
447 查看
在开淘宝店过程中需要批量下载图片时,利用【线程池】实现多线程【图片下载】功能,解决问题,这篇文章主要介绍此功能的实现细节。
工具主要可以细分为以下几个子部分:
1、读取excel中数据,提取数据中的图片URL
2、利用【线程池】实现多线程访问URL
3、将提交HTTP请求得到的图片保存到本地硬盘
1、读取excel中数据,提取数据中的图片URL
将需要进行处理的数据保存到excel文档中,作者为了图方便,就保存在第一列中,程序中访问的时候,直接读取第一列就行。
隐藏行号复制代码?代码
.src_container{background-color:#e7e5dc;width:99%;overflow:hidden;margin:12px012px0!important;padding:0px3px3px0px}
.src_container.titlebar{background-color:#d4dfff;border:1pxsolid#4f81bd;border-bottom:0;padding:3px24px;margin:0;width:auto;line-height:120%;overflow:hidden;text-align:left;font-size:12px}
.src_container.toolbar{display:inline;font-weight:normal;font-size:100%;float:right;cursor:hand;color:#00f;text-align:left;overflow:hidden}
.toolbarspan.button{display:inline;font-weight:normal;font-size:100%;cursor:hand;color:#00f;text-align:left;overflow:hidden;cursor:pointer;}
.src_containerdiv.clientarea{background-color:white;border:1pxsolid#4f81bd;margin:0;width:auto!important;width:100%;height:auto;overflow:auto;text-align:left;font-size:12px;font-family:"CourierNew","Consolas","Fixedsys",courier,monospace,serif}
.src_containerol.mainarea{padding:00052px;margin:0;background-color:#f7f7ff!important}
.number_show{padding-left:52px!important;list-style:decimaloutside!important}
.number_showli{list-style:decimaloutside!important;border-left:1pxdotted#4f81bd}
.number_hide{padding-left:0px!important;list-style-type:none!important}
.number_hideli{list-style-type:none!important;border-left:0px}
ol.mainareali{display:list-item!important;font-size:12px!important;margin:0!important;line-height:18px!important;padding:0000px!important;background-color:#f7f7ff!important;color:#4f81bd}
ol.mainarealipre{color:black;line-height:18px;padding:00012px!important;margin:0em;background-color:#fff!important}
.linewrapol.mainarealipre{white-space:pre-wrap;white-space:-moz-pre-wrapwhite-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}
ol.mainarealipre.alt{background-color:#f7f7ff!important}
functionCopyCode(key){varcodeElement=null;vartrElements=document.all.tags("ol");vari;for(i=0;i2、利用【线程池】实现多线程访问URL
为了实现多线程进行HTTP请求,将所有URL装在不同的List<string>对象中,而List<string>对象装在Dictionary<int,List<string>>中,每个线程实现对一组List<string>的访问,编程过程中可以定义每组List<string>的数目,间接就定义了Dictionary有多少个键值对,有多少个线程并行提交HTTP请求。
隐藏行号复制代码?代码
.src_container{background-color:#e7e5dc;width:99%;overflow:hidden;margin:12px012px0!important;padding:0px3px3px0px}
.src_container.titlebar{background-color:#d4dfff;border:1pxsolid#4f81bd;border-bottom:0;padding:3px24px;margin:0;width:auto;line-height:120%;overflow:hidden;text-align:left;font-size:12px}
.src_container.toolbar{display:inline;font-weight:normal;font-size:100%;float:right;cursor:hand;color:#00f;text-align:left;overflow:hidden}
.toolbarspan.button{display:inline;font-weight:normal;font-size:100%;cursor:hand;color:#00f;text-align:left;overflow:hidden;cursor:pointer;}
.src_containerdiv.clientarea{background-color:white;border:1pxsolid#4f81bd;margin:0;width:auto!important;width:100%;height:auto;overflow:auto;text-align:left;font-size:12px;font-family:"CourierNew","Consolas","Fixedsys",courier,monospace,serif}
.src_containerol.mainarea{padding:00052px;margin:0;background-color:#f7f7ff!important}
.number_show{padding-left:52px!important;list-style:decimaloutside!important}
.number_showli{list-style:decimaloutside!important;border-left:1pxdotted#4f81bd}
.number_hide{padding-left:0px!important;list-style-type:none!important}
.number_hideli{list-style-type:none!important;border-left:0px}
ol.mainareali{display:list-item!important;font-size:12px!important;margin:0!important;line-height:18px!important;padding:0000px!important;background-color:#f7f7ff!important;color:#4f81bd}
ol.mainarealipre{color:black;line-height:18px;padding:00012px!important;margin:0em;background-color:#fff!important}
.linewrapol.mainarealipre{white-space:pre-wrap;white-space:-moz-pre-wrapwhite-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}
ol.mainarealipre.alt{background-color:#f7f7ff!important}
functionCopyCode(key){varcodeElement=null;vartrElements=document.all.tags("ol");vari;for(i=0;i 3、将提交HTTP请求得到的图片保存到本地硬盘
这里将图片名称保存为整个URL连接,以避免不同图片重名的可能,而文件名不可包含“/”这个符号,用“@”替代(搜了一下,文件所有链接中没有用到这个符号的)。
隐藏行号复制代码?代码
.src_container{background-color:#e7e5dc;width:99%;overflow:hidden;margin:12px012px0!important;padding:0px3px3px0px}
.src_container.titlebar{background-color:#d4dfff;border:1pxsolid#4f81bd;border-bottom:0;padding:3px24px;margin:0;width:auto;line-height:120%;overflow:hidden;text-align:left;font-size:12px}
.src_container.toolbar{display:inline;font-weight:normal;font-size:100%;float:right;cursor:hand;color:#00f;text-align:left;overflow:hidden}
.toolbarspan.button{display:inline;font-weight:normal;font-size:100%;cursor:hand;color:#00f;text-align:left;overflow:hidden;cursor:pointer;}
.src_containerdiv.clientarea{background-color:white;border:1pxsolid#4f81bd;margin:0;width:auto!important;width:100%;height:auto;overflow:auto;text-align:left;font-size:12px;font-family:"CourierNew","Consolas","Fixedsys",courier,monospace,serif}
.src_containerol.mainarea{padding:00052px;margin:0;background-color:#f7f7ff!important}
.number_show{padding-left:52px!important;list-style:decimaloutside!important}
.number_showli{list-style:decimaloutside!important;border-left:1pxdotted#4f81bd}
.number_hide{padding-left:0px!important;list-style-type:none!important}
.number_hideli{list-style-type:none!important;border-left:0px}
ol.mainareali{display:list-item!important;font-size:12px!important;margin:0!important;line-height:18px!important;padding:0000px!important;background-color:#f7f7ff!important;color:#4f81bd}
ol.mainarealipre{color:black;line-height:18px;padding:00012px!important;margin:0em;background-color:#fff!important}
.linewrapol.mainarealipre{white-space:pre-wrap;white-space:-moz-pre-wrapwhite-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}
ol.mainarealipre.alt{background-color:#f7f7ff!important}
functionCopyCode(key){varcodeElement=null;vartrElements=document.all.tags("ol");vari;for(i=0;i 总结:刚开始的时候没考虑使用多线程进行保存的,而是为求简单,直接一个进程下载,用时20多分钟,后因为图片数量不断增多才考虑使用线程池进行下载,使用后效果很明显,虽然没有具体统计,但是快了好几倍是肯定的。
另外介绍下线程池与不用线程池之间的差别,个人认为,相比之下,线程池的效率效率是比较高的,因为减少了线程切换引起的上下文切换造成的资源消耗。所以这里选择了线程池,而不是简单的多线程搞定。
工具主要可以细分为以下几个子部分:
1、读取excel中数据,提取数据中的图片URL
2、利用【线程池】实现多线程访问URL
3、将提交HTTP请求得到的图片保存到本地硬盘
1、读取excel中数据,提取数据中的图片URL
将需要进行处理的数据保存到excel文档中,作者为了图方便,就保存在第一列中,程序中访问的时候,直接读取第一列就行。
隐藏行号复制代码?代码
staticDataTableExcelToDT(stringPath,stringtableName)
{
try
{
stringstrConn="Provider=Microsoft.Jet.OLEDB.4.0;"+"DataSource="+Path+";"+"ExtendedProperties='Excel8.0;'";
OleDbConnectionconn=newOleDbConnection(strConn);
conn.Open();
stringstrExcel="";
OleDbDataAdaptermyCommand=null;
DataSetds=null;
strExcel="select*from["+tableName+"$]";
myCommand=newOleDbDataAdapter(strExcel,strConn);
ds=newDataSet();
myCommand.Fill(ds,"table1");
conn.Close();
returnds.Tables["table1"];
}
catch
{
returnnull;
}
}
.src_container{background-color:#e7e5dc;width:99%;overflow:hidden;margin:12px012px0!important;padding:0px3px3px0px}
.src_container.titlebar{background-color:#d4dfff;border:1pxsolid#4f81bd;border-bottom:0;padding:3px24px;margin:0;width:auto;line-height:120%;overflow:hidden;text-align:left;font-size:12px}
.src_container.toolbar{display:inline;font-weight:normal;font-size:100%;float:right;cursor:hand;color:#00f;text-align:left;overflow:hidden}
.toolbarspan.button{display:inline;font-weight:normal;font-size:100%;cursor:hand;color:#00f;text-align:left;overflow:hidden;cursor:pointer;}
.src_containerdiv.clientarea{background-color:white;border:1pxsolid#4f81bd;margin:0;width:auto!important;width:100%;height:auto;overflow:auto;text-align:left;font-size:12px;font-family:"CourierNew","Consolas","Fixedsys",courier,monospace,serif}
.src_containerol.mainarea{padding:00052px;margin:0;background-color:#f7f7ff!important}
.number_show{padding-left:52px!important;list-style:decimaloutside!important}
.number_showli{list-style:decimaloutside!important;border-left:1pxdotted#4f81bd}
.number_hide{padding-left:0px!important;list-style-type:none!important}
.number_hideli{list-style-type:none!important;border-left:0px}
ol.mainareali{display:list-item!important;font-size:12px!important;margin:0!important;line-height:18px!important;padding:0000px!important;background-color:#f7f7ff!important;color:#4f81bd}
ol.mainarealipre{color:black;line-height:18px;padding:00012px!important;margin:0em;background-color:#fff!important}
.linewrapol.mainarealipre{white-space:pre-wrap;white-space:-moz-pre-wrapwhite-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}
ol.mainarealipre.alt{background-color:#f7f7ff!important}
functionCopyCode(key){varcodeElement=null;vartrElements=document.all.tags("ol");vari;for(i=0;i
为了实现多线程进行HTTP请求,将所有URL装在不同的List<string>对象中,而List<string>对象装在Dictionary<int,List<string>>中,每个线程实现对一组List<string>的访问,编程过程中可以定义每组List<string>的数目,间接就定义了Dictionary有多少个键值对,有多少个线程并行提交HTTP请求。
隐藏行号复制代码?代码
staticvoidSavePictureFromUrl()
{
List<string>PathList=newList<string>();
List<string>tempPathList=newList<string>();
DataTabledt=ExcelToDT("C:/b.xls","Sheet1");
intpathTempNum=0;
intDicKey=0;
foreach(DataRowrowindt.Rows)
{
if(pathTempNum==0)
{
tempPathList=newList<string>();
}
string[]a=row[0].ToString().Split(newstring[]{"src","background"},StringSplitOptions.None);
foreach(stringstrina)
{
if(str.Contains("jpg")||a.Contains("gif"))
{
stringpath=string.Empty;
path=str.Substring(str.IndexOf("http"),str.IndexOf("jpg")+str.IndexOf("gif")+4-str.IndexOf("http"));
if(PathList.IndexOf(path)<0)
{
PathList.Add(path);
tempPathList.Add(path);
pathTempNum++;
}
}
}
if(pathTempNum>100)
{
PathDic.Add(DicKey,tempPathList);
DicKey++;
pathTempNum=0;
}
}
ThreadPool.SetMaxThreads(100,100);
foreach(intkeyinPathDic.Keys)
{
ThreadPool.QueueUserWorkItem(newWaitCallback(SavePicFromDic),key);
}
}
.src_container{background-color:#e7e5dc;width:99%;overflow:hidden;margin:12px012px0!important;padding:0px3px3px0px}
.src_container.titlebar{background-color:#d4dfff;border:1pxsolid#4f81bd;border-bottom:0;padding:3px24px;margin:0;width:auto;line-height:120%;overflow:hidden;text-align:left;font-size:12px}
.src_container.toolbar{display:inline;font-weight:normal;font-size:100%;float:right;cursor:hand;color:#00f;text-align:left;overflow:hidden}
.toolbarspan.button{display:inline;font-weight:normal;font-size:100%;cursor:hand;color:#00f;text-align:left;overflow:hidden;cursor:pointer;}
.src_containerdiv.clientarea{background-color:white;border:1pxsolid#4f81bd;margin:0;width:auto!important;width:100%;height:auto;overflow:auto;text-align:left;font-size:12px;font-family:"CourierNew","Consolas","Fixedsys",courier,monospace,serif}
.src_containerol.mainarea{padding:00052px;margin:0;background-color:#f7f7ff!important}
.number_show{padding-left:52px!important;list-style:decimaloutside!important}
.number_showli{list-style:decimaloutside!important;border-left:1pxdotted#4f81bd}
.number_hide{padding-left:0px!important;list-style-type:none!important}
.number_hideli{list-style-type:none!important;border-left:0px}
ol.mainareali{display:list-item!important;font-size:12px!important;margin:0!important;line-height:18px!important;padding:0000px!important;background-color:#f7f7ff!important;color:#4f81bd}
ol.mainarealipre{color:black;line-height:18px;padding:00012px!important;margin:0em;background-color:#fff!important}
.linewrapol.mainarealipre{white-space:pre-wrap;white-space:-moz-pre-wrapwhite-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}
ol.mainarealipre.alt{background-color:#f7f7ff!important}
functionCopyCode(key){varcodeElement=null;vartrElements=document.all.tags("ol");vari;for(i=0;i
这里将图片名称保存为整个URL连接,以避免不同图片重名的可能,而文件名不可包含“/”这个符号,用“@”替代(搜了一下,文件所有链接中没有用到这个符号的)。
隐藏行号复制代码?代码
staticvoidSavePicFromDic(objectDicKey)
{
foreach(stringpathinPathDic[Convert.ToInt32(DicKey)])
{
Console.WriteLine(DicKey.ToString()+path);
SavePictureFromHTTP(path,@"G:\淘宝相关\图片\图片备份\"+path.Substring(7).Replace('/','@'));
}
}
staticvoidSavePictureFromHTTP(stringurl,stringpath)
{
try
{
longfileLength=0;
WebRequestwebReq=WebRequest.Create(url);
WebResponsewebRes=webReq.GetResponse();
fileLength=webRes.ContentLength;
Streamsrm=webRes.GetResponseStream();
StreamReadersrmReader=newStreamReader(srm);
byte[]bufferbyte=newbyte[fileLength];
intallByte=(int)bufferbyte.Length;
intstartByte=0;
while(fileLength>0)
{
intdownByte=srm.Read(bufferbyte,startByte,allByte);
if(downByte==0){break;};
startByte+=downByte;
allByte-=downByte;
}
if(File.Exists(path))
{
path=path.Insert(path.LastIndexOf('.'),Guid.NewGuid().ToString());
}
stringtempPath=path;
FileStreamfs=newFileStream(tempPath,FileMode.OpenOrCreate,FileAccess.Write);
fs.Write(bufferbyte,0,bufferbyte.Length);
srm.Close();
srmReader.Close();
fs.Close();
}
catch(WebExceptionex)
{
}
}
.src_container{background-color:#e7e5dc;width:99%;overflow:hidden;margin:12px012px0!important;padding:0px3px3px0px}
.src_container.titlebar{background-color:#d4dfff;border:1pxsolid#4f81bd;border-bottom:0;padding:3px24px;margin:0;width:auto;line-height:120%;overflow:hidden;text-align:left;font-size:12px}
.src_container.toolbar{display:inline;font-weight:normal;font-size:100%;float:right;cursor:hand;color:#00f;text-align:left;overflow:hidden}
.toolbarspan.button{display:inline;font-weight:normal;font-size:100%;cursor:hand;color:#00f;text-align:left;overflow:hidden;cursor:pointer;}
.src_containerdiv.clientarea{background-color:white;border:1pxsolid#4f81bd;margin:0;width:auto!important;width:100%;height:auto;overflow:auto;text-align:left;font-size:12px;font-family:"CourierNew","Consolas","Fixedsys",courier,monospace,serif}
.src_containerol.mainarea{padding:00052px;margin:0;background-color:#f7f7ff!important}
.number_show{padding-left:52px!important;list-style:decimaloutside!important}
.number_showli{list-style:decimaloutside!important;border-left:1pxdotted#4f81bd}
.number_hide{padding-left:0px!important;list-style-type:none!important}
.number_hideli{list-style-type:none!important;border-left:0px}
ol.mainareali{display:list-item!important;font-size:12px!important;margin:0!important;line-height:18px!important;padding:0000px!important;background-color:#f7f7ff!important;color:#4f81bd}
ol.mainarealipre{color:black;line-height:18px;padding:00012px!important;margin:0em;background-color:#fff!important}
.linewrapol.mainarealipre{white-space:pre-wrap;white-space:-moz-pre-wrapwhite-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}
ol.mainarealipre.alt{background-color:#f7f7ff!important}
functionCopyCode(key){varcodeElement=null;vartrElements=document.all.tags("ol");vari;for(i=0;i
另外介绍下线程池与不用线程池之间的差别,个人认为,相比之下,线程池的效率效率是比较高的,因为减少了线程切换引起的上下文切换造成的资源消耗。所以这里选择了线程池,而不是简单的多线程搞定。
相关文章推荐
- 【又拍图片相册跨分页下载图片/本地图片】合并及文字水印——淘宝开店过程中的技术应用【提供源代码下载】
- WPF技术触屏上的应用系列(一): 3D 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现
- WPF技术触屏上的应用系列(一): 3D 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现
- android图片获取、编辑、上传、下载、缓存、显示过程实现
- RxAndroid的简单应用——实现网络图片的下载
- WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、图片立体轮播、图片倒影立体滚动)效果实现
- 基于c++和linux的线程池技术及框架实现(网络下载,测试并修改其中可能的错误)
- 【JAVA秒会技术之玩转图片】图片下载和等比或指定大小压缩快速实现
- 新应用知识整理-图片的下载、内存软引用与本地缓存的实现
- 好多技术都有些相似!但实现过程和应用领域可能完全不同!
- 利用IDhttp实现图片下载
- 微信打印实现过程和免费下载
- newxy技术零java代码实现文件下载,下载记数 作者:胡立新
- 密码技术应用设计实践-安全信息传输系统(SITS)(用Java实现DES、RSA、MD5算法)
- Asp.net 2.0 用 FileUpload 控件实现多文件上传 用户控件(示例代码下载).NET技术
- jsoup实现网页图片下载
- Android 图片压缩实现过程代码
- 应用整合中SSO的技术实现(ZZ)
- 用Canvas+Javascript FileAPI 实现一个跨平台的图片剪切、滤镜处理、上传下载工具
- 综合使用spring cloud技术实现微服务应用