工具主要可以细分为以下几个子部分:
1、读取excel中数据,提取数据中的图片URL
2、利用【线程池】实现多线程访问URL
3、将提交HTTP请求得到的图片保存到本地硬盘
1、读取excel中数据,提取数据中的图片URL
将需要进行处理的数据保存到excel文档中,作者为了图方便,就保存在第一列中,程序中访问的时候,直接读取第一列就行。
static DataTable ExcelToDT(string Path, string tableName)
{
try
{
string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Path + ";" + "Extended Properties='Excel 8.0;'";
OleDbConnection conn = new OleDbConnection(strConn);
conn.Open();
string strExcel = "";
OleDbDataAdapter myCommand = null;
DataSet ds = null;
strExcel = "select * from [" + tableName + "$]";
myCommand = new OleDbDataAdapter(strExcel, strConn);
ds = new DataSet();
myCommand.Fill(ds, "table1");
conn.Close();
return ds.Tables["table1"];
}
catch
{
return null;
}
}
2、利用【线程池】实现多线程访问URL
为了实现多线程进行HTTP请求,将所有URL装在不同的List<string>对象中,而List<string>对象装在Dictionary<int, List<string>>中,每个线程实现对一组List<string>的访问,编程过程中可以定义每组List<string>的数目,间接就定义了Dictionary有多少个键值对,有多少个线程并行提交HTTP请求。
static void SavePictureFromUrl()
{
List<string> PathList = new List<string>();
List<string> tempPathList = new List<string>();
DataTable dt = ExcelToDT("C:/b.xls", "Sheet1");
int pathTempNum = 0;
int DicKey = 0;
foreach (DataRow row in dt.Rows)
{
if (pathTempNum == 0)
{
tempPathList = new List<string>();
}
string[] a = row[0].ToString().Split(new string[] { "src", "background" }, StringSplitOptions.None);
foreach (string str in a)
{
if (str.Contains("jpg") || a.Contains("gif"))
{
string path = 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 (int key in PathDic.Keys)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(SavePicFromDic), key);
}
}
3、将提交HTTP请求得到的图片保存到本地硬盘
这里将图片名称保存为整个URL连接,以避免不同图片重名的可能,而文件名不可包含“/”这个符号,用“@”替代(搜了一下,文件所有链接中没有用到这个符号的)。