通过c#使用JSON请求和RestSharp上传文件

本文关键字:RestSharp 文件 求和 请求 使用 JSON 通过 | 更新日期: 2023-09-27 17:50:29

通过c#管理加载数据到我的Rails服务器后(检查这里知道我在说什么),我现在试图将文件上传到同一服务器,以及其他数据。

在Ruby中,我可以这样做:

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

当我检查rails服务器上的参数时,我看到

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"}}

但是如果我尝试在

下面的c#代码中做同样的事情
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;


        }
    }
}

我得到这个

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

这似乎意味着Restsharp只是认为我的文件只是另一个字段。

RestSharp似乎有一个方法来添加文件request.AddFile("receipt/receipt_file",path);,我相信这应该是要走的路…但是当我尝试添加文件时,我得到一个错误消息说:

写入开始后不能设置此属性。

我需要单独设置文件的每个属性吗?

编辑

同时我发现了这篇文章,把我的代码改为:

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);
                }
            });
        }
    }
}

,现在我得到参数:

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"}}

伴随着HTTP 422 - Unprocessable Entity错误。

如果我将这些参数与我从ruby代码中工作的参数进行比较,现在唯一的区别似乎是最后一条消息没有Content-length和Content-Transfer-Encoding字段…

你知道我该如何添加属性吗?

通过c#使用JSON请求和RestSharp上传文件

这是一场战斗…最后,我发现了两种不同的方法来解决这个问题。具有讽刺意味的是,就像许多编码问题一样,我所要做的就是首先设置正确的参数……仅仅是少了一个参数,我就花了4个多小时。

详情如下:

1 -使用RestSharp (total字段不应该在那里,ispaperduplicate字段丢失)

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 -使用FileStream与HttpWebRequest(谢谢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();
        }
    }
}