2

i am working on a project that need to upload files from iphone to wcf service. i dont have experience on both wcf and afnetworking. i've stuck on this step for days and heres the progress that i've made:

WCF Service for uploading files: note that i've copied this code from Codeproject website.

public interface ITransferService
{
[OperationContract]
RemoteFileInfo DownloadFile(DownloadRequest request);

[OperationContract]
 void UploadFile(RemoteFileInfo request); 
}

    public void UploadFile(RemoteFileInfo request)
{
    FileStream targetStream = null;
    Stream sourceStream =  request.FileByteStream;

    string uploadFolder = @"C:\upload\";

    string filePath = Path.Combine(uploadFolder, request.FileName);

    using (targetStream = new FileStream(filePath, FileMode.Create, 
                          FileAccess.Write, FileShare.None))
    {
        //read from the input stream in 65000 byte chunks

        const int bufferLen = 65000;
        byte[] buffer = new byte[bufferLen];
        int count = 0;
        while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
        {
            // save to output stream
            targetStream.Write(buffer, 0, count);
        }
        targetStream.Close();
        sourceStream.Close();
    }

}

The upload code works good on the client program came with the sourcode, i can upload any size and any type or files through the wcf service.

I've also found that AFNetworking framework is quite popular on ios, so i've decided to use it. heres my code for uploading file:

i've come this far, please help me in this situation. thanks for helping

OK, heres the new information:

Fırst of all, the c# code to upload file to the wcf service (which is working)

protected void Button1_Click(object sender, EventArgs e)
{ 
if (FileUpload1.HasFile)
{
    System.IO.FileInfo fileInfo = 
           new System.IO.FileInfo(FileUpload1.PostedFile.FileName);
    FileTransferServiceReference.ITransferService clientUpload = 
           new FileTransferServiceReference.TransferServiceClient();
    FileTransferServiceReference.RemoteFileInfo 
           uploadRequestInfo = new RemoteFileInfo();

    using (System.IO.FileStream stream = 
           new System.IO.FileStream(FileUpload1.PostedFile.FileName, 
           System.IO.FileMode.Open, System.IO.FileAccess.Read))
    {
        uploadRequestInfo.FileName = FileUpload1.FileName;
        uploadRequestInfo.Length = fileInfo.Length;
        uploadRequestInfo.FileByteStream = stream;
        clientUpload.UploadFile(uploadRequestInfo);
        //clientUpload.UploadFile(stream);
    }
}
}

Second: The remotefileinfo class that used to upload file to server:

  public class RemoteFileInfo : IDisposable
  {
    [MessageHeader(MustUnderstand = true)]
     public string **FileName**;

    [MessageHeader(MustUnderstand = true)]
    public long **Length**;

    [MessageBodyMember(Order = 1)]
    public System.IO.Stream **FileByteStream**;

    public void Dispose()
    { 
        if (FileByteStream != null)
       {
        FileByteStream.Close();
        FileByteStream = null;
       }
    }   
  }

From all those code i understand that i need to create a request that contains "Filename" "FileLength" and the filedata "FileByteStream". i tried something in the codes but the server gives error 415 when i try to upload image with this code:

   AFHTTPClient *client= [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://192.168.2.121:85"]];

UIImage *image = [UIImage imageNamed:@"test.jpg"];
NSData *data = UIImageJPEGRepresentation(image, 0.2);

NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
[parameters setObject:@"test.jpg" forKey:@"FileName"];
[parameters setObject:[NSString stringWithFormat:@"%i",data.length] forKey:@"Length"];

NSMutableURLRequest *myRequest = [client multipartFormRequestWithMethod:@"POST" path:@"/webservice/Transferservice.svc/UploadFile" parameters:parameters constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
    [formData appendPartWithFileData:data name:@"RemoteFileInfo" fileName:@"test.jpg" mimeType:@"image/jpeg"];
}];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:myRequest];
[operation 
 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
     NSLog(@"success: %@", operation.responseString);
 } 
 failure:^(AFHTTPRequestOperation *operation, NSError *error) {
     NSLog(@"error: %@", operation.error);
 }
 ];

[[[NSOperationQueue alloc] init] addOperation:operation];

also here is the WSDL Link for the service :

WSDL Link

i really need to do this, thanks for helping again...

dreampowder
  • 1,644
  • 3
  • 25
  • 41

3 Answers3

3

Try this for size:

AFHTTPClient *client= [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://192.168.2.121:85"]];

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"test.jpg"], 0.2);

NSMutableURLRequest *myRequest = [client multipartFormRequestWithMethod:@"POST" path:@"/webservice/Transferservice.svc/UploadFile" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
    [formData appendPartWithFileData:data name:@"RemoteFileInfo" fileName:@"test.jpg" mimeType:@"image/jpeg"];
}];

AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:myRequest] autorelease];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *op, id responseObj) {
    NSLog(@"success: %@", operation.responseString);
} failure:^(AFHTTPRequestOperation *op, NSError *error) {
    NSLog(@"[Error]: (%@ %@) %@", [operation.request HTTPMethod], [[operation.request URL] relativePath], operation.error);
}];

NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
[queue addOperation:operation];

You shouldn't need to pass the name of you file or the size in your post parameters you can pick this up on the receiving form. Don't forget that the name part of the appendPartWithFileData should be used by you server side script to identify the file upload.

All the above is relevant in PHP but should work the same for ASP.NET.

Also like above the link doesn't work.

Cheers

Sam Soffes
  • 14,831
  • 9
  • 76
  • 80
iamsmug
  • 1,517
  • 4
  • 15
  • 25
  • thank you for the answer, i tried the code yo've given but i got error 415 now. From what i've researched, the WCF service is looking for a stream instead of a nsdata. So i tried to send the data as an "operation.inputStream". but when i do that i get "request body stream exhausted" error. i Guess i will give up an write a new service from that question: http://stackoverflow.com/questions/1354749/wcf-service-to-accept-a-post-encoded-multipart-form-data – dreampowder Nov 27 '11 at 12:51
1

Finally, i've succeded on uploading a file to WCF via filestream. The problem was the previous code was expecting a header and a stream in the body which i couldnt find a way to do that. instead, i've found that i need to write a code that only acceps a stream as parameter, nothing much, and then the filename and other stuff will be done at the serverside.

i've got that upload code for wcf service from this question: WCF service to accept a post encoded multipart/form-data

did exactly whats written in the answer. and in the iphone side, i've setup an inputstream for my operation. heres the code for the AFNetworking for uploading files to the wcf service:

AFHTTPClient *client= [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://192.168.2.121:85"]];

UIImage *image = [UIImage imageNamed:@"test.jpg"];
NSData *data = UIImageJPEGRepresentation(image, 0.2);
NSInputStream *stream = [[[NSInputStream alloc]initWithData:data] retain];
NSDictionary *parameters = nil;

NSMutableURLRequest *myRequest = [client requestWithMethod:@"POST" path:@"/uploadservice/service1.svc/Upload" parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:myRequest];

 [
 operation 
 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
     NSLog(@"success: %@", operation.responseString);
 } 
 failure:^(AFHTTPRequestOperation *operation, NSError *error) {
     NSLog(@"error: %@", operation.error);
 }
 ];

operation.inputStream = stream; //Thats where you put your stream!

[[[NSOperationQueue alloc] init] addOperation:operation];

Thanks everyone for their patience, even your replies wasnt the complete answer, your replies led me to the correct answers...

Community
  • 1
  • 1
dreampowder
  • 1,644
  • 3
  • 25
  • 41
  • 1
    I want to mention that in my case in one project Sam Soffes's solution worked fine, for other project solution of dream powder worked. It all depends on server API needs. So check both ways and read API documentation carefully. – Nikolay Shubenkov Feb 25 '14 at 07:11
0

You're getting a 404, or "Not found" error back from the remote web server.

This probably means you have an incorrect URL path or server name - there's not enough information about the server side setup for us to deduce what the correct URL would be.

JosephH
  • 37,173
  • 19
  • 130
  • 154
  • what do you need to know about the server setup? i 'll provide it with the post again, maybe i can provide the wsdl data ? – dreampowder Nov 23 '11 at 14:43
  • 1
    Everything I guess. The wsdl might help - though; do you realise that it appears you've implemented a SOAP webservice, and the iOS code you've included isn't sending a SOAP request? Or have you enabled REST on the WCF side? – JosephH Nov 23 '11 at 14:49
  • heres the WSDL Link: http://caspetrol.dyndns.org:85/webservice/TransferService.svc?wsdl – dreampowder Nov 23 '11 at 14:53
  • btw, i really dont know what i am doing in here, i worked with xml webservices recently with simple parameters and return values. this is just a new dimension for me ;) – dreampowder Nov 23 '11 at 15:45
  • 1
    You seem to have a mismatch - your iOS code is not sending SOAP, your WCF service is expecting SOAP... are you wanting to use SOAP or REST? (REST is probably better) – JosephH Nov 24 '11 at 10:10
  • As i've seen from code there is no rest endpoint in config.. What is the difference btw soap vs rest and how can i send rest or soap request?? – dreampowder Nov 24 '11 at 11:59
  • Joesph, i put some new information into the question, i guess i need to send "Remotefileinfo" with the request somehow.. – dreampowder Nov 24 '11 at 13:15