8

在设法通过 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 字段......

您对我如何添加属性有任何想法吗?

4

1 回答 1

13

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

两者详述如下:

1 - 使用 RestSharp(总字段不应该存在,并且 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();

        }

    }

}
于 2013-01-03T23:01:09.877 回答