您的位置:首页 > 其它

淘宝开店过程中的技术应用——【线程池】实现【图片下载】

2011-03-16 09:47 447 查看
在开淘宝店过程中需要批量下载图片时,利用【线程池】实现多线程【图片下载】功能,解决问题,这篇文章主要介绍此功能的实现细节。

工具主要可以细分为以下几个子部分:

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;i2、利用【线程池】实现多线程访问URL

为了实现多线程进行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;i3、将提交HTTP请求得到的图片保存到本地硬盘

这里将图片名称保存为整个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总结:刚开始的时候没考虑使用多线程进行保存的,而是为求简单,直接一个进程下载,用时20多分钟,后因为图片数量不断增多才考虑使用线程池进行下载,使用后效果很明显,虽然没有具体统计,但是快了好几倍是肯定的。

另外介绍下线程池与不用线程池之间的差别,个人认为,相比之下,线程池的效率效率是比较高的,因为减少了线程切换引起的上下文切换造成的资源消耗。所以这里选择了线程池,而不是简单的多线程搞定。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐