2012-02-24 7 views
6

Zaimplementowałem kod C# za pomocą interfejsu API tłumaczenia Google V2 z metodą GET. Pomyślnie tłumaczy małe teksty, ale przy zwiększaniu długości tekstu i długości 1800 znaków (w tym parametry URI) otrzymuję błąd "Zbyt duży URI".Google Translate V2 nie może hanldować dużych tłumaczeń tekstowych z C#

Ok, spaliłem wszystkie ścieżki i zbadałem problem na wielu stronach opublikowanych w Internecie. Wszystkie wyraźnie mówią, że metoda GET powinna zostać przesłonięta, aby symulować metodę POST (która ma zapewnić obsługę 5 000 znaków URI), ale nie ma sposobu, aby znaleźć przykład kodu do niej.

Czy ktoś ma przykład lub może dostarczyć pewnych informacji?

[EDIT] Oto kod używam:

String apiUrl = "https://www.googleapis.com/language/translate/v2?key={0}&source={1}&target={2}&q={3}"; 
      String url = String.Format(apiUrl, Constants.apiKey, sourceLanguage, targetLanguage, text); 
      Stream outputStream = null; 

     byte[] bytes = Encoding.ASCII.GetBytes(url); 

     // create the http web request 
     HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); 
     webRequest.KeepAlive = true; 
     webRequest.Method = "POST"; 
     // Overrride the GET method as documented on Google's docu. 
     webRequest.Headers.Add("X-HTTP-Method-Override: GET"); 
     webRequest.ContentType = "application/x-www-form-urlencoded"; 

     // send POST 
     try 
     { 
      webRequest.ContentLength = bytes.Length; 
      outputStream = webRequest.GetRequestStream(); 
      outputStream.Write(bytes, 0, bytes.Length); 
      outputStream.Close(); 
     } 
     catch (HttpException e) 
     { 
      /*...*/ 
     } 

     try 
     { 
      // get the response 
      HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); 
      if (webResponse.StatusCode == HttpStatusCode.OK && webRequest != null) 
      { 
       // read response stream 
       using (StreamReader sr = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8)) 
       { 
        string lista = sr.ReadToEnd(); 

        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(TranslationRootObject)); 
        MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(lista)); 
        TranslationRootObject tRootObject = (TranslationRootObject)serializer.ReadObject(stream); 
        string previousTranslation = string.Empty; 

        //deserialize 
        for (int i = 0; i < tRootObject.Data.Detections.Count; i++) 
        { 
         string translatedText = tRootObject.Data.Detections[i].TranslatedText.ToString(); 
         if (i == 0) 
         { 
          text = translatedText; 
         } 
         else 
         { 
          if (!text.Contains(translatedText)) 
          { 
           text = text + " " + translatedText; 
          } 
         } 
        } 
        return text; 
       } 
      } 
     } 
     catch (HttpException e) 
     { 
      /*...*/ 
     } 

     return text; 
    } 
+0

Czy możesz pokazać nam swój kod, którego teraz używasz? Strategia jest nieco inna, jeśli używasz 'WebClient' kontra' WebRequest'. – user7116

Odpowiedz

7

Widocznie za pomocą WebClient nie będzie działać, ponieważ nie można zmienić nagłówki, ile potrzeba, per the documentation:

Note: You can also use POST to invoke the API if you want to send more data in a single request. The q parameter in the POST body must be less than 5K characters. To use POST, you must use the X-HTTP-Method-Override header to tell the Translate API to treat the request as a GET (use X-HTTP-Method-Override: GET).

Można użyć WebRequest, ale trzeba dodać X-HTTP-Method-Override nagłówka:

var request = WebRequest.Create (uri); 
request.Method = "POST"; 
request.ContentType = "application/x-www-form-urlencoded"; 
request.Headers.Add("X-HTTP-Method-Override", "GET"); 

var body = new StringBuilder(); 
body.Append("key=SECRET"); 
body.AppendFormat("&source={0}", HttpUtility.UrlEncode(source)); 
body.AppendFormat("&target={0}", HttpUtility.UrlEncode(target)); 
//-- 
body.AppendFormat("&q={0}", HttpUtility.UrlEncode(text)); 

var bytes = Encoding.ASCII.GetBytes(body.ToString()); 
if (bytes.Length > 5120) throw new ArgumentOutOfRangeException("text"); 

request.ContentLength = bytes.Length; 
using (var output = request.GetRequestStream()) 
{ 
    output.Write(bytes, 0, bytes.Length); 
} 
+0

Dziękujemy za szybką odpowiedź. Dodałem kod, który wykonuję. Wkopiowałem się również w opublikowany przeze mnie kod i mogłem zaktualizować moje kopie, aby opublikować post, o czym wspomniałeś. Jednak podczas wykonywania "request.GetResponse();" pojawia się następujący błąd: "Serwer zdalny zwrócił błąd: (400) Złe żądanie". Zajrzę w to. – G21

+0

@ George_21: musisz pozbyć się parametrów z adresu URL i umieścić je wszystkie w treści postu. – user7116

+1

Jesteś moim bohaterem! : P. W końcu udało mi się ponownie napisać kod po sugestii, a także dodać brakującą linię: "request.ContentType =" application/x-www-form-urlencoded "; Naprawdę doceniam twoją pomoc w tej sprawie! Thankssss! – G21

-3

? Co? wpisywanie przy użyciu języka C# jest trywialne - znajduje się w dokumentacji.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
{ 
    // Set type to POST 
    request.Method = "POST"; 

Stamtąd zasadniczo umieszczasz dane w polach FOM w strumieniu treści.

To nie jest "symulacja post meethod", w pełni robi post, zgodnie ze specyfikacją.

Przy okazji. Gdzie tu wchodzi json? Mówisz "w języku C#". Nie ma potrzeby używania json?

+0

Nie obsługuje części "X-HTTP-Override metody". – Suma

1

Przyjęta odpowiedź wydaje się być nieaktualna. Możesz teraz używać WebClient (.net 4.5) z powodzeniem do POST do interfejsu Google Translate API, upewniając się, że ustawiłeś nagłówek X-HTTP-Method-Override.

Oto kod, który pokazuje, w jaki sposób.

using (var webClient = new WebClient()) 
{ 
    webClient.Headers.Add("X-HTTP-Method-Override", "GET"); 
    var data = new NameValueCollection() 
    { 
     { "key", GoogleTranslateApiKey }, 
     { "source", "en" }, 
     { "target", "fr"}, 
     { "q", "<p>Hello World</p>" } 
    }; 
    try 
    { 
     var responseBytes = webClient.UploadValues(GoogleTranslateApiUrl, "POST", data); 
     var json = Encoding.UTF8.GetString(responseBytes); 
     var result = JsonConvert.DeserializeObject<dynamic>(json); 
     var translation = result.data.translations[0].translatedText; 
    } 
    catch (Exception ex) 
    { 
     loggingService.Error(ex.Message); 
    } 
}