2013-01-03 19 views
8

Dopo aver effettuato il caricamento dei dati sul mio Rails Server tramite C# (controllareper sapere di cosa sto parlando), sto provando a caricare un file sullo stesso server, insieme a altri dati.Carica file tramite C# utilizzando JSON request e RestSharp

In Ruby, sono in grado di fare questo con il codice:

require 'HTTMultiParty' 

    class ReceiptCreate 
     include HTTMultiParty 
     # Log to file 
     # debug_output File.new("httparty1.log", "w+") 
     base_uri "localhost:3000" 
     format :json 
     headers "Accept" => "application/json" 

     def initialize 
     end 

     def post(machine_serial,filepath,tag_number,token) 
     options = { body: 
        {receipt: 
         {tag_number:tag_number, 
         receipt_file: File.new(filepath), 
         ispaperduplicate:0 
         }, 
        machine: 
         {serial_number: machine_serial, 
         safe_token: token 
         } 
        }    
       } 
     self.class.post('/receipts', options) 
     end 
    end 

receipt = ReceiptCreate.new() 
filename1 = "C:\\filename1.pdf" 
filename2 = "C:\\filename2.pdf" 
response=receipt.post("2803433",filename2,"p94tt7w","123") 
puts response 

una quando ho ispezionare i parametri sul server rotaie vedo

Parameters: {"receipt"=>{"tag_number"=>"p94tt7w", "receipt_file"=>#<ActionDispatch::Http::UploadedFile:0x4183ea8 @original_filename="Invoice.pdf", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"receipt[receipt_file]\"; filename=\"Invoice.pdf\"\r\nContent-Length: 11653\r\nContent-Type: application/octet-stream\r\nContent-Transfer-Encoding: binary\r\n", @tempfile=#<File:C:/Users/diogo/AppData/Local/Temp/RackMultipart20130103-18168-efiqia>>, "ispaperduplicate"=>"0"}, "machine"=>{"serial_number"=>"2803433", "safe_token"=>"123"}} 

Ma se provo a fare il stessa cosa con il mio codice C# sotto

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using RestSharp; 
using System.Web.Script.Serialization; 
using System.IO; 

namespace RonRestClient 
{ 


    class templateRequest 
    { 
     public Receipt receipt; 
     public class Receipt 
     { 
      public float total; 
      public String tag_number; 
      public bool ispaperduplicate = true; 
      public byte[] receipt_file; 
      public Receipt(float total, String tagnr, string filepath) 
      { 
       this.total = total; 
       this.tag_number = tagnr; 
       this.receipt_file = File.ReadAllBytes(filepath); 
      } 
     }; 
     public Machine machine; 
     public class Machine 
     { 
      public String serial_number; 
      public String safe_token; 
      public Machine(String machinenr, String safe_token) 
      { 
       this.serial_number = machinenr; 
       this.safe_token = safe_token; 
      } 
     }; 
    } 


    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 

      string path = @"C:\filename2.pdf"; 
      string tagnr = "p94tt7w"; 
      string machinenr = "2803433"; 
      string safe_token = "123"; 
      float total = 100; 

      templateRequest req = new templateRequest(); 
      req.receipt = new templateRequest.Receipt(total, tagnr, path); 
      req.machine = new templateRequest.Machine(machinenr, safe_token); 
      //string json_body = JsonConvert.SerializeObject(req); 
      //string json_body = new JavaScriptSerializer().Serialize(req); 


      //var json_body = "{\"receipt\" : {\"total\":"+total+", \"tag_number\":\""+tagnr+"\",\"ispaperduplicate\":true},\"machine\":{\"serial_number\": \""+machinenr+"\",\"safe_token\": \""+safe_token+"\"}}"; 

      var client = new RestClient("http://localhost:3000/receipts"); 

      var request = new RestRequest(Method.POST); 


      //set request Body 
      request.AddHeader("Content-type", "application/json"); 
      request.AddHeader("Accept", "application/json"); 
      request.RequestFormat = DataFormat.Json; 

      request.AddBody(req); 
      //request.AddParameter("application/json", json_body, ParameterType.RequestBody); 

      // easily add HTTP Headers 


      // add files to upload (works with compatible verbs) 
      //request.AddFile("receipt/receipt_file",path); 

      // execute the request 

      IRestResponse response = client.Execute(request); 
      var content = response.Content; // raw content as string 
      if(response.ErrorMessage !="") content += response.ErrorMessage; 
      response_box.Text = content; 




     } 
    } 
} 

ottengo questo

012.
Parameters: {"receipt"=>{"total"=>100, "tag_number"=>"p94tt7w", "ispaperduplicate"=>true, "receipt_file"=>[37, 80, [n3...nX], 10]}, "machine"=>{"serial_number"=>"2803433", "safe_token"=>"123"}} 

Questo sembra significare sostanzialmente che Restsharp pensa solo che il mio file sia solo un altro campo.

RestSharp sembra avere un metodo per aggiungere i file request.AddFile("receipt/receipt_file",path);, e credo che questo dovrebbe essere probabilmente la strada da percorrere ... ma quando cerco solo e aggiungere il file, viene visualizzato un messaggio di errore che dice:

Questa proprietà non può essere impostata dopo l'inizio della scrittura.

Devo impostare separatamente ciascun attributo del file?

EDIT

Nel frattempo ho trovato questo post, cambiato il mio codice a:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using RestSharp; 
using System.Web.Script.Serialization; 
using System.IO; 
using System.Net; 

namespace RonRestClient 
{ 


    class templateRequest 
    { 
     public Receipt receipt; 
     public class Receipt 
     { 
      //public float total; 
      public String tag_number; 
      public bool ispaperduplicate = true; 
      //public byte[] receipt_file; 
      public Receipt(String tagnr) 
      { 
       //this.total = total; 
       this.tag_number = tagnr; 
       // this.receipt_file = File.ReadAllBytes(filepath); 
      } 
     }; 
     public Machine machine; 
     public class Machine 
     { 
      public String serial_number; 
      public String safe_token; 
      public Machine(String machinenr, String safe_token) 
      { 
       this.serial_number = machinenr; 
       this.safe_token = safe_token; 
      } 
     }; 
    } 


    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 

      string path = @"C:\filename2.pdf"; 
      string tagnr = "p94tt7w"; 
      string machinenr = "2803433"; 
      string safe_token = "123"; 
      float total = 100; 

      templateRequest req = new templateRequest(); 
      req.receipt = new templateRequest.Receipt(tagnr); 
      req.machine = new templateRequest.Machine(machinenr, safe_token); 

      var request = new RestRequest("/receipts",Method.POST); 
      request.AddParameter("receipt[total]", total); 
      request.AddParameter("receipt[tag_number]", tagnr); 
      request.AddParameter("machine[serial_number]", machinenr); 
      request.AddParameter("machine[safe_token]", safe_token); 
      request.AddFile("receipt[receipt_file]", File.ReadAllBytes(path), "Invoice.pdf", "application/octet-stream"); 

      // Add HTTP Headers 
      request.AddHeader("Content-type", "application/json"); 
      request.AddHeader("Accept", "application/json"); 
      request.RequestFormat = DataFormat.Json; 
      //set request Body 
      //request.AddBody(req); 


      // execute the request 
      //calling server with restClient 
      RestClient restClient = new RestClient("http://localhost:3000"); 
      restClient.ExecuteAsync(request, (response) => 
      { 

       if (response.StatusCode == HttpStatusCode.OK) 
       { 
        //upload successfull 
        MessageBox.Show("Upload completed succesfully...\n" + response.Content); 
       } 
       else 
       { 
        //error ocured during upload 
        MessageBox.Show(response.StatusCode + "\n" + response.StatusDescription); 
       } 
      }); 

     } 

    } 

} 

e ora sto ricevendo i parametri:

Parameters: {"receipt"=>{"total"=>"100", "tag_number"=>"p94tt7w", "receipt_file"=>#<ActionDispatch::Http::UploadedFile:0x3db42d8 @original_filename="Invoice.pdf", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"receipt[receipt_file]\"; filename=\"Invoice.pdf\"\r\nContent-Type: application/octet-stream\r\n", @tempfile=#<File:C:/Users/diogo/AppData/Local/Temp/RackMultipart20130103-18168-9mbt3h>>}, "machine"=>{"serial_number"=>"2803433", "safe_token"=>"123"}} 

Insieme con un HTTP 422 - Unprocessable Errore entità.

Se devo confrontare questi parametri con quelli che ho a che fare con il codice ruby, ora l'unica differenza sembra essere che questo ultimo messaggio non ha i campi Content-length e Content-Transfer-Encoding.

Avete qualche idea su come aggiungere gli attributi?

risposta

13

Questo è stato un combattimento ... Alla fine ho scoperto due modi diversi per risolvere questo problema. L'ironia di questo, come molti dei problemi di codifica, era che tutto quello che dovevo fare era impostare i parametri corretti al primo posto ... Solo un parametro mancante mi è costato più di 4 ore ..

Entrambi di seguito dettagliate:

1 - Usare RestSharp (il campo totale non dovrebbe essere lì, e il campo ispaperduplicate mancava)

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using RestSharp; 
using System.Web.Script.Serialization; 
using System.IO; 
using System.Net; 

namespace RonRestClient 
{  

    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 

      string path = @"C:\filename2.pdf"; 
      //localhost settings 
      string requestHost = @"http://localhost:3000/receipts"; 
      string tagnr = "p94tt7w"; 
      string machinenr = "2803433"; 
      string safe_token = "123"; 

      // Do it with RestSharp 

      templateRequest req = new templateRequest(); 
      req.receipt = new templateRequest.Receipt(tagnr); 
      req.machine = new templateRequest.Machine(machinenr, safe_token); 

      var request = new RestRequest("/receipts", Method.POST); 
      request.AddParameter("receipt[tag_number]", tagnr); 
      request.AddParameter("receipt[ispaperduplicate]", 0); 
      request.AddParameter("machine[serial_number]", machinenr); 
      request.AddParameter("machine[safe_token]", safe_token); 
      request.AddFile("receipt[receipt_file]", File.ReadAllBytes(path), Path.GetFileName(path), "application/octet-stream"); 

      // Add HTTP Headers 
      request.AddHeader("Content-type", "application/json"); 
      request.AddHeader("Accept", "application/json"); 
      request.RequestFormat = DataFormat.Json; 
      //set request Body 
      //request.AddBody(req); 


      // execute the request 
      //calling server with restClient 
      RestClient restClient = new RestClient("http://localhost:3000"); 
      restClient.ExecuteAsync(request, (response) => 
      { 

       if (response.StatusCode == HttpStatusCode.OK) 
       { 
        //upload successfull 
        MessageBox.Show("Upload completed succesfully...\n" + response.Content); 
       } 
       else 
       { 
        //error ocured during upload 
        MessageBox.Show(response.StatusCode + "\n" + response.StatusDescription); 
       } 
      }); 

     } 

    } 

} 

2 - Utilizzare FileStream con HttpWebRequest (grazie Clivant)

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using RestSharp; 
using System.Web.Script.Serialization; 
using System.IO; 
using System.Net; 

namespace RonRestClient 
{ 

    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 

      string path = @"C:\Projectos\My Training Samples\Adobe Sample\RBO1574.pdf"; 
      //localhost settings 
      string requestHost = @"http://localhost:3000/receipts"; 
      string tagnr = "p94tt7w"; 
      string machinenr = "2803433"; 
      string safe_token = "123"; 

      FileStream fs1 = File.OpenRead(path); 
      long filesize = fs1.Length; 
      fs1.Close(); 

      // Create a http request to the server endpoint that will pick up the 
      // file and file description. 
      HttpWebRequest requestToServerEndpoint = 
       (HttpWebRequest)WebRequest.Create(requestHost); 

      string boundaryString = "FFF3F395A90B452BB8BEDC878DDBD152"; 
      string fileUrl = path; 

      // Set the http request header \\ 
      requestToServerEndpoint.Method = WebRequestMethods.Http.Post; 
      requestToServerEndpoint.ContentType = "multipart/form-data; boundary=" + boundaryString; 
      requestToServerEndpoint.KeepAlive = true; 
      requestToServerEndpoint.Credentials = System.Net.CredentialCache.DefaultCredentials; 
      requestToServerEndpoint.Accept = "application/json"; 


      // Use a MemoryStream to form the post data request, 
      // so that we can get the content-length attribute. 
      MemoryStream postDataStream = new MemoryStream(); 
      StreamWriter postDataWriter = new StreamWriter(postDataStream); 

      // Include value from the tag_number text area in the post data 
      postDataWriter.Write("\r\n--" + boundaryString + "\r\n"); 
      postDataWriter.Write("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", 
            "receipt[tag_number]", 
            tagnr); 

      // Include ispaperduplicate text area in the post data 
      postDataWriter.Write("\r\n--" + boundaryString + "\r\n"); 
      postDataWriter.Write("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", 
            "receipt[ispaperduplicate]", 
            0); 

      // Include value from the machine number in the post data 
      postDataWriter.Write("\r\n--" + boundaryString + "\r\n"); 
      postDataWriter.Write("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", 
            "machine[serial_number]", 
            machinenr); 

      // Include value from the machine token in the post data 
      postDataWriter.Write("\r\n--" + boundaryString + "\r\n"); 
      postDataWriter.Write("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", 
            "machine[safe_token]", 
            safe_token); 

      // Include the file in the post data 
      postDataWriter.Write("\r\n--" + boundaryString + "\r\n"); 
      postDataWriter.Write("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" 
            + "Content-Length: \"{2}\"\r\n" 
            + "Content-Type: application/octet-stream\r\n" 
            + "Content-Transfer-Encoding: binary\r\n\r\n", 
            "receipt[receipt_file]", 
            Path.GetFileName(fileUrl), 
            filesize); 

      postDataWriter.Flush(); 


      // Read the file 
      FileStream fileStream = new FileStream(fileUrl, FileMode.Open, FileAccess.Read); 
      byte[] buffer = new byte[1024]; 
      int bytesRead = 0; 
      while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) 
      { 
       postDataStream.Write(buffer, 0, bytesRead); 
      } 
      fileStream.Close(); 

      postDataWriter.Write("\r\n--" + boundaryString + "--\r\n"); 
      postDataWriter.Flush(); 

      // Set the http request body content length 
      requestToServerEndpoint.ContentLength = postDataStream.Length; 

      // Dump the post data from the memory stream to the request stream 
      Stream s = requestToServerEndpoint.GetRequestStream(); 

      postDataStream.WriteTo(s); 

      postDataStream.Close(); 

     } 

    } 

}