2011-04-04 357 views
1

我想要通過BING上傳一個多行文本文件來GeoCoded。Delphi使用HTTP上傳一個文本文件

1,en-US,,16630 Redmond Way,WA,USA,,,Redmond,98052,,,,,,,,,,,,,,,,,,,,,, 
2,en-US,,16552 NE 74th St,WA,,,,Redmond,,,High,,,,,,,,,,,,,,,,,,,,,, 
3,en-US,Seattle Space Needle,,,,,,,,,,,,,,,,,,,,,,,,,,,, 
4,en-US,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 
5,en-US,,W Jefferson Blvd,CA,,,,Los Angeles,90007,,,,,,,,,,,,,,,,,,,,,,,, 
6,en-US,,,CA,,,,Los angeles,,,,,,,,,,,,,,,,,,,,,,,,, 
7,en-ca,Montreal Canada,,,,,,,,,,,,,,,,,,,,,,,,,,,, 
8,en-CA,,444 Kirkpatrick Cres NW,AB,Canada,,,Edmonton,,,,,,,,,,,,,,,,,,,,,,,, 
9,en-gb,BD4 9JB,,,,,,,,,,,,,,,,,,,,,,,,,,,, 
10,en-us,,,,,,,,,,,,,,,,,,,,,,,,,,,,47.673099,-122.11871 
11,en-ca,,,,,,,,,,,,,,,,,,,,,,,,,,,,53.48021728,-113.4030925 
12,en-gb,,,,,,,,,,,,,,,,,,,,,,,,,,,,53.77848387,-1.719561517 

我使用TIdHTTP的時刻,但似乎在文本文件中的換行符被刪除傳輸文件時,他們應(Bing),只有永遠的地理編碼文件,其餘的第一線被忽略。

lHTTP := TIdHTTP.Create(nil); 
... 

//Build the http request string 
HTTPRequest := 'http://spatial.virtualearth.net/REST/v1/Dataflows/Geocode?input=csv&output=xml&key=' + BingKey; 

//Setup the HTTP request parameters 
lHTTP.Request.ContentType := 'text/plain'; 
lHTTP.Request.Method := 'POST'; 

//Send the request to Bing. Result in XMLResult StringStream 
lHTTP.Post(HTTPRequest, lParamList, XMLResult); 

下面的例子是從Microsoft但我沒有足夠的專家,以適應使用流德爾福的部分HttpWebRequest的。任何人都可以幫忙嗎?

//Parameters: 
// dataFilePath: The path to the file that contains the spatial data to geocode. 
// dataFormat: The format of the input data. Possible values are xml, csv, tab and pipe. 
// key: The Bing Maps Key to use for this job. The same key is used to get job status and download results. 
// description: Text that is used to describe the geocode dataflow job. 
//Return value : A URL that defines the location of the geocode dataflow job that was created. 
static string CreateJob(string dataFilePath, string dataFormat, string key, string description) 
{ 
    //Define parameters for the HTTP request 
    // 
    // The 'Content-Type' header of the HTTP Request must be "text/plain" or "application/xml" 
    // depending on the input data format. 
    // 
    string contentType = "text/plain"; 
    if (dataFormat.Equals("xml", StringComparison.OrdinalIgnoreCase)) 
     contentType = "application/xml"; 

    StringBuilder queryStringBuilder = new StringBuilder(); 

    // 
    // The 'input'(input format) and 'key' (Bing Maps Key) parameters are required. 
    // 
    queryStringBuilder.Append("input=").Append(Uri.EscapeUriString(dataFormat)); 
    queryStringBuilder.Append("&"); 
    queryStringBuilder.Append("key=").Append(Uri.EscapeUriString(key)); 

    if (!String.IsNullOrEmpty(description)) 
    { 
     // 
     // The 'description' parameter is optional. 
     // 
     queryStringBuilder.Append("&"); 
     queryStringBuilder.Append("description=").Append(Uri.EscapeUriString(description)); 
    } 

    //Build the HTTP URI that will upload and create the geocode dataflow job 
    UriBuilder uriBuilder = new UriBuilder("http://spatial.virtualearth.net"); 
    uriBuilder.Path = "/REST/v1/dataflows/geocode"; 
    uriBuilder.Query = queryStringBuilder.ToString(); 

    //Include the data to geocode in the HTTP request 
    using (FileStream dataStream = File.OpenRead(dataFilePath)) 
    { 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriBuilder.Uri); 

     // 
     // The HTTP method must be 'POST'. 
     // 
     request.Method = "POST"; 
     request.ContentType = contentType; 

     using (Stream requestStream = request.GetRequestStream()) 
     { 
      byte[] buffer = new byte[16384]; 
      int bytesRead = dataStream.Read(buffer, 0, buffer.Length); 
      while (bytesRead > 0) 
      { 
       requestStream.Write(buffer, 0, bytesRead); 

       bytesRead = dataStream.Read(buffer, 0, buffer.Length); 
      } 
     } 

     //Submit the HTTP request and check if the job was created successfully. 
     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
     { 
      // 
      // If the job was created successfully, the status code should be 
      // 201 (Created) and the 'Location' header should contain a URL 
      // that defines the location of the new dataflow job. You use this 
      // URL with the Bing Maps Key to query the status of your job. 
      // 
      if (response.StatusCode != HttpStatusCode.Created) 
       throw new Exception ("An HTTP error status code was encountered when creating the geocode job."); 

      string dataflowJobLocation = response.GetResponseHeader("Location"); 
      if (String.IsNullOrEmpty(dataflowJobLocation)) 
       throw new Exception ("The 'Location' header is missing from the HTTP response when creating a goecode job."); 

      return dataflowJobLocation; 
     } 
    } 
} 
+0

你如何構建lParamlist? – mjn 2011-04-04 14:37:50

+0

lParamList是一個TStringList。我從文本文件(Addresses.txt)加載文件。 – 2011-04-04 16:08:40

+2

嘗試將文件作爲純流發送。只需將其加載到TMemoryStream或使用TFileStream即可。這樣您將發佈原始文件中的數據。 Indy對不同的發送帖子方法有重載。只需使用Post重載之一。 – Runner 2011-04-04 17:01:13

回答

0

很可能TStringList正在改變輸入文件的內容。至少有一些字節。最好將數據作爲純粹的流發佈,無論是作爲內存還是文件流。

印有發佈以下重載方法:

function Post(AURL: string; ASource: TStrings): string; overload; 
function Post(AURL: string; ASource: TStream): string; overload; 
function Post(AURL: string; ASource: TIdMultiPartFormDataStream): string; overload; 
procedure Post(AURL: string; ASource: TIdMultiPartFormDataStream; AResponseContent: TStream); overload; 
procedure Post(AURL: string; ASource: TStrings; AResponseContent: TStream); overload; 

{Post data provided by a stream, this is for submitting data to a server} 
procedure Post(AURL: string; ASource, AResponseContent: TStream); overload; 

其中有幾個適合張貼原料流。

1

比較代碼的2個要點。首先,您將代碼作爲text/plain發送,而不是application/xml,然後將它們轉義出來,然後發送XML。你有沒有試過它作爲逃脫的數據?

+0

我在url * ...?input = csv&output = xml ... *中指定了文本輸入。我不確定如何將其作爲「轉義」數據發送? – 2011-04-04 13:26:45

+0

在Delphi代碼中,XML是POST響應,而不是POST數據(URL中的'input = csv&output = xml') – mjn 2011-04-04 14:39:48

+0

@Pieter轉義只對包含'unreserved'字符的'BingKey'是必需的 - 請參閱http ://en.wikipedia.org/wiki/Percent-encoding,不需要轉義'csv'或'xml',因爲這些參數值只包含未保留的字符 – mjn 2011-04-04 15:07:09