Reputation: 502
while creating WCF REST service, i am receiving data in json and able to save in database. now i need to give option to upload file(optional, image or video) with same service. i tried sending byte array but it is giving bad request error possibly because of serialization of such a long array. i read that to upload large files i need to use stream. how would i do that while sending other parameters? i am creating this service to receive data from mobile device. here is my service interface
[WebInvoke(UriTemplate = "SaveFBPost",
Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
void SaveFacebookPost(FBPostData fbPostData);
public class FBPostData:
[DataMember]
public string scheduleDate { get; set; }
[DataMember]
public string userId { get; set; }
[DataMember]
public string groupId { get; set; }
[DataMember]
public string postText { get; set; }
[DataMember]
public byte[] file { get; set; }
[DataMember]
public string fileType { get; set; }
[DataMember]
public string accessToken { get; set; }
Upvotes: 1
Views: 1510
Reputation: 502
i had to use stream using multipart upload from android and multipart parser to solve this issue. i used Apache mime library to upload file and send parameters like this:
HttpPost postRequest = new HttpPost(
context.getString(R.string.url_service_fbpost));
MultipartEntity reqEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
if(postData.data != null && !"".equals(postData.fileName)){
ByteArrayBody bab = new ByteArrayBody(postData.data, postData.fileName);
reqEntity.addPart("uploaded", bab);
}
reqEntity.addPart("scheduleDate", new StringBody(postData.scheduleDate));
reqEntity.addPart("userId", new StringBody(postData.userId));
reqEntity.addPart("groupIds",
new StringBody(postData.groupIds.toString()));
reqEntity.addPart("postText", new StringBody(postData.postText));
reqEntity.addPart("postType", new StringBody(postData.postType));
reqEntity.addPart("accessToken", new StringBody(postData.accessToken));
if(postData.postId != null && postData.postId.length() > 0) {
reqEntity.addPart("postId", new StringBody(postData.postId));
}
postRequest.setEntity(reqEntity);
after that i used c# multipart parser to get file and parameters. here is the code for service:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "UploadFBPost",
BodyStyle = WebMessageBodyStyle.WrappedRequest)]
void UploadFBPost(Stream stream);
public void UploadFBPost(Stream stream)
{
MultipartParser parser = new MultipartParser(stream);
// Saves post data in database
if (parser.Success)
{
string fileName = null, userId = null, postText = null, postType = null, accessToken = null;
DateTime scheduleDate = DateTime.Now;
string[] groupIds = null;
int postId = 0;
// Other contents
foreach (MyContent content in parser.MyContents)
{
switch (content.PropertyName)
{
case "scheduleDate":
if (string.IsNullOrEmpty(content.StringData.Trim()))
scheduleDate = DateTime.Now;
else
scheduleDate = DateTime.ParseExact(content.StringData.Trim(), "M-d-yyyy H:m:s", CultureInfo.InvariantCulture);
break;
case "fileName":
fileName = content.StringData.Trim();
break;
case "userId":
userId = content.StringData.Trim();
break;
case "postText":
postText = content.StringData.Trim();
break;
case "accessToken":
accessToken = content.StringData.Trim();
break;
case "groupIds":
groupIds = content.StringData.Trim().Split(new char[] { ',' });
break;
case "postType":
postType = content.StringData.Trim();
break;
case "postId":
postId = Convert.ToInt32(content.StringData.Trim());
break;
}
}
string videoFile = null, imageFile = null;
if (parser.FileContents != null)
{
string filePath = GetUniqueUploadFileName(parser.Filename);
File.WriteAllBytes(filePath, parser.FileContents);
if (postType == "photo")
imageFile = Path.GetFileName(filePath);
else
videoFile = Path.GetFileName(filePath);
}
}
}
you do need to modify multipart parser according to data you are sending. hope this will save time of few.
thanks ray for the help.
one more thing. i had to add these lines in web config:
<httpRuntime maxRequestLength="2000000"/>
<bindings>
<webHttpBinding>
<binding maxBufferSize="65536"
maxReceivedMessageSize="2000000000"
transferMode="Streamed">
</binding>
</webHttpBinding>
</bindings>
Upvotes: 1
Reputation: 1442
I would start by increasing maxBufferSize and maxArrayLength for the particular binding in the web.config, and see if that resolves the issue.
You should be able to pull up some more specifics on the error as well, so you can see exactly why you are getting your 400 error.
This blog article was also useful for me in the past - there are some good links at the bottom as well.
Also take look at the Stream class. Not sure what you mean by "sending other parameters" - If you can clarify this, we can give you some more direction on that.
Upvotes: 1