WCF 服务使用来自 android 的多部分数据
WCF service to consume Multipart data from android
我正在使用 android okhttp 将多部分数据(即图像和文本)发送到 wcf 服务。我能够使用自定义 MultipartParser class 在服务器上发送和解析部分数据,如前所述 here.
当我的文件写入服务器时,由于多部分数据中的一些不需要的字符被用字节写入,它被损坏[我通过在记事本++中打开显示编码字节和不需要的字符的图像发现了这一点]。
我可以通过为 contentLenMatch 添加正则表达式匹配器来删除它们,但仍然在文件开头写入换行符,因此将其显示为已损坏。
我需要知道如何在将数据写入文件之前删除数据中的空格或 \n。
代码:
public class MultipartParser {
public IDictionary<string, string> Parameters = new Dictionary<string, string>();
public MultipartParser(Stream stream) {
this.Parse(stream, Encoding.UTF8);
}
public MultipartParser(Stream stream, Encoding encoding) {
this.Parse(stream, encoding);
}
public string getcontent(Stream stream, Encoding encoding) {
byte[] data = ToByteArray(stream);
string content = encoding.GetString(data);
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
string[] sections = content.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in sections) {
Match nameMatch = new Regex(@"(?<=name\=\"")(.*?)(?=\"")").Match(s);
string name = nameMatch.Value.Trim().ToLower();
if (!string.IsNullOrWhiteSpace(name)) {
int startIndex = nameMatch.Index + nameMatch.Length + "\r\n\r\n".Length;
}
string strRet = ""; //Parameters["name"];
return strRet;
}
private void Parse(Stream stream, Encoding encoding) {
this.Success = false;
byte[] data = ToByteArray(stream);
string content = encoding.GetString(data);
int delimiterEndIndex = content.IndexOf("\r\n");
if (delimiterEndIndex > -1) {
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
Regex re = new Regex(@"(?<=Content\-Type:)(.*?)");
Match contentTypeMatch = re.Match(content);
re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
Match filenameMatch = re.Match(content);
// to match Content-Length and remove ***Unwanted chars***
re = new Regex(@"(?<=Content\-Length:)(.*)");
Match contentLenMatch = re.Match(content);
if(contentLenMatch.Success){
contentLenMatch = contentLenMatch.NextMatch();
}
if (contentTypeMatch.Success && filenameMatch.Success) {
this.ContentType = contentTypeMatch.Value.Trim();
this.Filename = filenameMatch.Value.Trim();
// changed from contentTypeMatch to contentLenMatch
// startIndex must point to the 1st byte
// from where the file needs to be written
// Need to remove extra \n that gets written to the file
int startIndex = contentLenMatch.Index + contentLenMatch .Length + "\r\n\r\n".Length;
byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
int endIndex = IndexOf(data, delimiterBytes, startIndex);
int contentLength = endIndex - startIndex;
byte[] fileData = new byte[contentLength];
Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
this.FileContents = fileData;
this.Success = true; }
} }
private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex) {
int index = 0;
int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
if (startPos != -1) {
while ((startPos + index) < searchWithin.Length) {
if (searchWithin[startPos + index] == serachFor[index]) {
index++;
if (index == serachFor.Length) {
return startPos;
}
} else {
startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index);
if (startPos == -1) {
return -1;
}
index = 0;
}
}
}
return -1;
}
private byte[] ToByteArray(Stream stream) {
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream()) {
while (true) {
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
public bool Success {
get;
private set;
}
public string ContentType {
get;
private set;
}
public string Filename {
get;
private set;
}
public byte[] FileContents {
get;
private set;
}
public string Imgname {
get;
private set;
}
好的,我很早就通过尝试和错误的基础解决了这个问题,但由于没有人回复我发布了我的解决方案。
public class MultipartParser
{
public IDictionary<string, string> Parameters = new Dictionary<string, string>();
public MultipartParser(Stream stream)
{
this.Parse(stream, Encoding.UTF8);
}
public MultipartParser(Stream stream, Encoding encoding)
{
this.Parse(stream, encoding);
}
public string getcontent(Stream stream, Encoding encoding)
{
// Read the stream into a byte array
byte[] data = ToByteArray(stream);
// Copy to a string for header parsing
string content = encoding.GetString(data);
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
string[] sections = content.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in sections)
{
Match nameMatch = new Regex(@"(?<=name\=\"")(.*?)(?=\"")").Match(s);
string name = nameMatch.Value.Trim().ToLower();
if (!string.IsNullOrWhiteSpace(name))
{
int startIndex = nameMatch.Index + nameMatch.Length + "\r\n\r\n".Length;
}
}
string strRet = ""; //Parameters["name"];
return strRet;
}
private void Parse(Stream stream, Encoding encoding)
{
this.Success = false;
byte[] data = ToByteArray(stream);
string content = encoding.GetString(data);
string s_no = content.Substring(content.IndexOf("s_no"), 100);
string[] lines = s_no.Split(new[] { "\r\n", "\r\n\r\n" }, StringSplitOptions.None);
this.S_NO = lines[3];
string count = content.Substring(content.IndexOf("Count"), 100);
string[] linescount = count.Split(new[] { "\r\n", "\r\n\r\n" }, StringSplitOptions.None);
this.Count = linescount[3];
int delimiterEndIndex = content.IndexOf("\r\n");
if (delimiterEndIndex > -1)
{
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
// Look for Content-Type
Regex re = new Regex(@"(?<=Content\-Type:)(.*?)");
Match contentTypeMatch = re.Match(content);
// Look for filename
re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
Match filenameMatch = re.Match(content);
re = new Regex(@"(?<=Content\-Length:)(.*)");
Match contentLenMatch = re.Match(content);
if (contentLenMatch.Success)
{
contentLenMatch = contentLenMatch.NextMatch();
}
if (contentLenMatch.Success)
{
contentLenMatch = contentLenMatch.NextMatch();
}
//re = new Regex(@"(?<=name\=\"")(.*?)(?=\"")");
//Match nameMatch = re.Match(content);
// Did we find the required values?
if (contentTypeMatch.Success && filenameMatch.Success)
{
// Set properties
this.ContentType = contentTypeMatch.Value.Trim();
this.Filename = filenameMatch.Value.Trim();
// Get the start & end indexes of the file contents
int startIndex = contentLenMatch.Index + contentLenMatch.Length + "\r\n".Length + 1;
byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
int endIndex = IndexOf(data, delimiterBytes, startIndex);
int contentLength = endIndex - startIndex;
// Extract the file contents from the byte array
byte[] fileData = new byte[contentLength];
Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
this.FileContents = fileData;
this.Success = true;
}
}
}
private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex)
{
int index = 0;
int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
if (startPos != -1)
{
while ((startPos + index) < searchWithin.Length)
{
if (searchWithin[startPos + index] == serachFor[index])
{
index++;
if (index == serachFor.Length)
{
return startPos;
}
}
else
{
startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index);
if (startPos == -1)
{
return -1;
}
index = 0;
}
}
}
return -1;
}
private byte[] ToByteArray(Stream stream)
{
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
public bool Success
{
get;
private set;
}
public string ContentType
{
get;
private set;
}
public string Filename
{
get;
private set;
}
public byte[] FileContents
{
get;
private set;
}
public string Imgname
{
get;
private set;
}
public string S_NO
{
get;
private set;
}
public string Count
{
get;
private set;
}
}
// End of Wcf rest Service Code
我的Android代码如下所示使用Okhttp
public static ResultVO uploadIMGMultipart(String s_no, int noOfDocs, String filepath, String url) {
ResultVO resultVO = new ResultVO();
OkHttpClient client = new OkHttpClient().newBuilder()
.retryOnConnectionFailure(false)
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.build();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("s_no",s_no.toString())
.addFormDataPart("Count", ""+noOfDocs)
.addFormDataPart("filestream", new File(filepath).getName().toString(), RequestBody.create(MEDIA_TYPE_PNG, new File(filepath)))
.build();
Request request = new Request.Builder()
.url(url)
.addHeader("content-type", "multipart/form-data;")
.cacheControl(CacheControl.FORCE_NETWORK)
.post(requestBody)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
resultVO.setStatus(response.code());
resultVO.setResult(response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
return resultVO;
}
从您的 class 调用 AsyncTask 中的上述方法就可以了....
给你…
MyService.cs
[OperationContract]
[WebInvoke(Method = "POST",ResponseFormat = WebMessageFormat.Json,BodyStyle = WebMessageBodyStyle.Wrapped,UriTemplate = "/UPLOAD_DOCUMENTS")]
string UPLOAD_DOCUMENTS(Stream fileStream);
IMyService.svc.cs
public string UPLOAD_DOCUMENTS(Stream fileStream)
{
string ResponseMessage = "Documents Not Uploaded";
string strRet = string.Empty;
string strpdffile = string.Empty;
string VAR_CLAIM_INWARD_NO = "";
string response = string.Empty;
int i = 0;
string tempFolderPath = string.Empty;
string UPLOADED_BY = string.Empty;
string VAR_NEXT_FILE_NO = "";
string s_no = string.Empty;
string count = string.Empty;
try
{
MultipartParser parser = new MultipartParser(fileStream);
if (parser.Success)
{
string fileName = parser.Filename;
string contentType = parser.ContentType;
byte[] fileContent = parser.FileContents;
Encoding encoding = Encoding.UTF8;
s_no = parser.S_NO;
count = parser.Count;
string savepathImg = @"Your path" + fileNameToBeSaved + ".jpg";
FileStream fileToupload = new FileStream(savepathImg, FileMode.Create);
fileToupload.Write(fileContent, 0, fileContent.Length);
fileToupload.Close();
fileToupload.Dispose();
fileStream.Close();
strRet = fileName;
tempFolderPath = @"Your path";
}
else
{
}
}
catch (Exception ex)
{
}
return ResponseMessage;
}
我正在使用 android okhttp 将多部分数据(即图像和文本)发送到 wcf 服务。我能够使用自定义 MultipartParser class 在服务器上发送和解析部分数据,如前所述 here.
当我的文件写入服务器时,由于多部分数据中的一些不需要的字符被用字节写入,它被损坏[我通过在记事本++中打开显示编码字节和不需要的字符的图像发现了这一点]。 我可以通过为 contentLenMatch 添加正则表达式匹配器来删除它们,但仍然在文件开头写入换行符,因此将其显示为已损坏。
我需要知道如何在将数据写入文件之前删除数据中的空格或 \n。
代码:
public class MultipartParser {
public IDictionary<string, string> Parameters = new Dictionary<string, string>();
public MultipartParser(Stream stream) {
this.Parse(stream, Encoding.UTF8);
}
public MultipartParser(Stream stream, Encoding encoding) {
this.Parse(stream, encoding);
}
public string getcontent(Stream stream, Encoding encoding) {
byte[] data = ToByteArray(stream);
string content = encoding.GetString(data);
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
string[] sections = content.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in sections) {
Match nameMatch = new Regex(@"(?<=name\=\"")(.*?)(?=\"")").Match(s);
string name = nameMatch.Value.Trim().ToLower();
if (!string.IsNullOrWhiteSpace(name)) {
int startIndex = nameMatch.Index + nameMatch.Length + "\r\n\r\n".Length;
}
string strRet = ""; //Parameters["name"];
return strRet;
}
private void Parse(Stream stream, Encoding encoding) {
this.Success = false;
byte[] data = ToByteArray(stream);
string content = encoding.GetString(data);
int delimiterEndIndex = content.IndexOf("\r\n");
if (delimiterEndIndex > -1) {
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
Regex re = new Regex(@"(?<=Content\-Type:)(.*?)");
Match contentTypeMatch = re.Match(content);
re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
Match filenameMatch = re.Match(content);
// to match Content-Length and remove ***Unwanted chars***
re = new Regex(@"(?<=Content\-Length:)(.*)");
Match contentLenMatch = re.Match(content);
if(contentLenMatch.Success){
contentLenMatch = contentLenMatch.NextMatch();
}
if (contentTypeMatch.Success && filenameMatch.Success) {
this.ContentType = contentTypeMatch.Value.Trim();
this.Filename = filenameMatch.Value.Trim();
// changed from contentTypeMatch to contentLenMatch
// startIndex must point to the 1st byte
// from where the file needs to be written
// Need to remove extra \n that gets written to the file
int startIndex = contentLenMatch.Index + contentLenMatch .Length + "\r\n\r\n".Length;
byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
int endIndex = IndexOf(data, delimiterBytes, startIndex);
int contentLength = endIndex - startIndex;
byte[] fileData = new byte[contentLength];
Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
this.FileContents = fileData;
this.Success = true; }
} }
private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex) {
int index = 0;
int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
if (startPos != -1) {
while ((startPos + index) < searchWithin.Length) {
if (searchWithin[startPos + index] == serachFor[index]) {
index++;
if (index == serachFor.Length) {
return startPos;
}
} else {
startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index);
if (startPos == -1) {
return -1;
}
index = 0;
}
}
}
return -1;
}
private byte[] ToByteArray(Stream stream) {
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream()) {
while (true) {
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
public bool Success {
get;
private set;
}
public string ContentType {
get;
private set;
}
public string Filename {
get;
private set;
}
public byte[] FileContents {
get;
private set;
}
public string Imgname {
get;
private set;
}
好的,我很早就通过尝试和错误的基础解决了这个问题,但由于没有人回复我发布了我的解决方案。
public class MultipartParser
{
public IDictionary<string, string> Parameters = new Dictionary<string, string>();
public MultipartParser(Stream stream)
{
this.Parse(stream, Encoding.UTF8);
}
public MultipartParser(Stream stream, Encoding encoding)
{
this.Parse(stream, encoding);
}
public string getcontent(Stream stream, Encoding encoding)
{
// Read the stream into a byte array
byte[] data = ToByteArray(stream);
// Copy to a string for header parsing
string content = encoding.GetString(data);
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
string[] sections = content.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in sections)
{
Match nameMatch = new Regex(@"(?<=name\=\"")(.*?)(?=\"")").Match(s);
string name = nameMatch.Value.Trim().ToLower();
if (!string.IsNullOrWhiteSpace(name))
{
int startIndex = nameMatch.Index + nameMatch.Length + "\r\n\r\n".Length;
}
}
string strRet = ""; //Parameters["name"];
return strRet;
}
private void Parse(Stream stream, Encoding encoding)
{
this.Success = false;
byte[] data = ToByteArray(stream);
string content = encoding.GetString(data);
string s_no = content.Substring(content.IndexOf("s_no"), 100);
string[] lines = s_no.Split(new[] { "\r\n", "\r\n\r\n" }, StringSplitOptions.None);
this.S_NO = lines[3];
string count = content.Substring(content.IndexOf("Count"), 100);
string[] linescount = count.Split(new[] { "\r\n", "\r\n\r\n" }, StringSplitOptions.None);
this.Count = linescount[3];
int delimiterEndIndex = content.IndexOf("\r\n");
if (delimiterEndIndex > -1)
{
string delimiter = content.Substring(0, content.IndexOf("\r\n"));
// Look for Content-Type
Regex re = new Regex(@"(?<=Content\-Type:)(.*?)");
Match contentTypeMatch = re.Match(content);
// Look for filename
re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
Match filenameMatch = re.Match(content);
re = new Regex(@"(?<=Content\-Length:)(.*)");
Match contentLenMatch = re.Match(content);
if (contentLenMatch.Success)
{
contentLenMatch = contentLenMatch.NextMatch();
}
if (contentLenMatch.Success)
{
contentLenMatch = contentLenMatch.NextMatch();
}
//re = new Regex(@"(?<=name\=\"")(.*?)(?=\"")");
//Match nameMatch = re.Match(content);
// Did we find the required values?
if (contentTypeMatch.Success && filenameMatch.Success)
{
// Set properties
this.ContentType = contentTypeMatch.Value.Trim();
this.Filename = filenameMatch.Value.Trim();
// Get the start & end indexes of the file contents
int startIndex = contentLenMatch.Index + contentLenMatch.Length + "\r\n".Length + 1;
byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
int endIndex = IndexOf(data, delimiterBytes, startIndex);
int contentLength = endIndex - startIndex;
// Extract the file contents from the byte array
byte[] fileData = new byte[contentLength];
Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
this.FileContents = fileData;
this.Success = true;
}
}
}
private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex)
{
int index = 0;
int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
if (startPos != -1)
{
while ((startPos + index) < searchWithin.Length)
{
if (searchWithin[startPos + index] == serachFor[index])
{
index++;
if (index == serachFor.Length)
{
return startPos;
}
}
else
{
startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index);
if (startPos == -1)
{
return -1;
}
index = 0;
}
}
}
return -1;
}
private byte[] ToByteArray(Stream stream)
{
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
public bool Success
{
get;
private set;
}
public string ContentType
{
get;
private set;
}
public string Filename
{
get;
private set;
}
public byte[] FileContents
{
get;
private set;
}
public string Imgname
{
get;
private set;
}
public string S_NO
{
get;
private set;
}
public string Count
{
get;
private set;
}
}
// End of Wcf rest Service Code
我的Android代码如下所示使用Okhttp
public static ResultVO uploadIMGMultipart(String s_no, int noOfDocs, String filepath, String url) {
ResultVO resultVO = new ResultVO();
OkHttpClient client = new OkHttpClient().newBuilder()
.retryOnConnectionFailure(false)
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.build();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("s_no",s_no.toString())
.addFormDataPart("Count", ""+noOfDocs)
.addFormDataPart("filestream", new File(filepath).getName().toString(), RequestBody.create(MEDIA_TYPE_PNG, new File(filepath)))
.build();
Request request = new Request.Builder()
.url(url)
.addHeader("content-type", "multipart/form-data;")
.cacheControl(CacheControl.FORCE_NETWORK)
.post(requestBody)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
resultVO.setStatus(response.code());
resultVO.setResult(response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
return resultVO;
}
从您的 class 调用 AsyncTask 中的上述方法就可以了....
给你…
MyService.cs
[OperationContract]
[WebInvoke(Method = "POST",ResponseFormat = WebMessageFormat.Json,BodyStyle = WebMessageBodyStyle.Wrapped,UriTemplate = "/UPLOAD_DOCUMENTS")]
string UPLOAD_DOCUMENTS(Stream fileStream);
IMyService.svc.cs
public string UPLOAD_DOCUMENTS(Stream fileStream)
{
string ResponseMessage = "Documents Not Uploaded";
string strRet = string.Empty;
string strpdffile = string.Empty;
string VAR_CLAIM_INWARD_NO = "";
string response = string.Empty;
int i = 0;
string tempFolderPath = string.Empty;
string UPLOADED_BY = string.Empty;
string VAR_NEXT_FILE_NO = "";
string s_no = string.Empty;
string count = string.Empty;
try
{
MultipartParser parser = new MultipartParser(fileStream);
if (parser.Success)
{
string fileName = parser.Filename;
string contentType = parser.ContentType;
byte[] fileContent = parser.FileContents;
Encoding encoding = Encoding.UTF8;
s_no = parser.S_NO;
count = parser.Count;
string savepathImg = @"Your path" + fileNameToBeSaved + ".jpg";
FileStream fileToupload = new FileStream(savepathImg, FileMode.Create);
fileToupload.Write(fileContent, 0, fileContent.Length);
fileToupload.Close();
fileToupload.Dispose();
fileStream.Close();
strRet = fileName;
tempFolderPath = @"Your path";
}
else
{
}
}
catch (Exception ex)
{
}
return ResponseMessage;
}