在设法通过 C# 将数据加载到我的 Rails 服务器之后(查看 here 了解我在说什么),我现在尝试将一个文件连同其他数据一起上传到同一服务器。
在 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);,我相信这应该是可行的方法...但是当我只是尝试添加文件,但收到一条错误消息:
This property cannot be set after writing has started.
是否需要分别设置文件的每个属性?
编辑
与此同时,我发现了这个 post ,将我的代码更改为:
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 - 无法处理的实体错误。
如果我要将这些参数与我在 ruby 代码中使用的参数进行比较,现在唯一的区别似乎是最后一条消息没有 Content-length 和 Content-Transfer-Encoding 字段......
您知道我如何添加属性吗?
最佳答案
这是一场战斗......最后我发现了两种不同的方法来解决这个问题。具有讽刺意味的是,就像许多编码问题一样,我所要做的就是首先设置正确的参数……仅仅缺少一个参数就让我花费了 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();
}
}
}
关于c# - 使用 JSON 请求和 RestSharp 通过 c# 上传文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14143630/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题