1

I'm trying to upload a text file (.csv) saved within my iOS application's tmp directory to a web server at a url that uses a Django form (and works fine from a browser uploading files off a computer). I'm having trouble getting the Swift code to work and getting request.FILES to not be empty. I tried using the answer to this question with the NSRLSession code from this page but I can't get request.FILES to behave.

My main question is: what should I do to give the request the right stored key and info that the Django form will use (in this case, make sure the key 'docfile'), and associate that with the text file I want to send?

Below is the code I have so far (apologies for any strange formatting):

ViewController.swift Code

    class ViewController: UIViewController, NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate {


        let defaults = NSUserDefaults.standardUserDefaults()
        var fileManager = NSFileManager()
        var tmpDir = NSURL(fileURLWithPath: NSTemporaryDirectory())
        var responseData = NSMutableData()

        override func viewDidLoad() {
            super.viewDidLoad()

            // Do any additional setup after loading the view.
        }

        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }

        @IBAction func sendFileToServer(){
            //get file name
            if let fileName = defaults.stringForKey("fileNameKey")
            {
                let getPath = tmpDir.URLByAppendingPathComponent(fileName)
                let data: NSData = NSData(contentsOfFile: getPath.path!)!

    //setup major parts of HTTP request here
                let request = NSMutableURLRequest(URL: NSURL(string: "http://mywebserverurl.goeshere/upload/")!)
                let HTTPMethod: String = "POST"
                request.HTTPMethod = HTTPMethod

    //set up more important HTTP request info here
                let boundary = "----SomeSortOfRandomStringGoesHere"
                let contentType = "multipart/form-data; boundary=\(boundary)"
                request.setValue(contentType, forHTTPHeaderField:"Content-Type")

                let body = NSMutableData()
                let tempData = NSMutableData()

                let parameterName = "docfile"
                let mimeType = "file"
                tempData.appendData("--\(boundary)\r\n--".dataUsingEncoding(NSUTF8StringEncoding)!)
                let fileNameContentDisposition =  "filename=\"\(fileName)\""
                let contentDisposition = "Content-Disposition: form-data; name=\"\(parameterName)\"; \(fileNameContentDisposition)\r\n"

tempData.appendData(contentDisposition.dataUsingEncoding(NSUTF8StringEncoding)!)
                tempData.appendData("Content-Type: \(mimeType)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
                tempData.appendData(data)
            tempData.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

body.appendData(tempData)
                body.appendData("\r\n--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)


request.setValue("\(body.length)", forHTTPHeaderField: "Content-Length")
                request.HTTPBody = body

                uploadFiles(request, data: data)
            }

        }


        func uploadFiles(request: NSURLRequest, data: NSData) {
            let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
            let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
            let task = session.uploadTaskWithRequest(request, fromData: data)
            task.resume()
        }

        func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
            if error != nil {
                print("session \(session) occurred error \(error?.localizedDescription)")
            } else {
                print("session \(session), response: \(NSString(data: responseData, encoding: NSUTF8StringEncoding))")
            }
        }

        func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
            let uploadProgress: Float = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
            print("session \(session) uploaded \(uploadProgress * 100)%.")
        }

        func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
            print("session \(session), received response \(response)")
            completionHandler(NSURLSessionResponseDisposition.Allow)
        }

        func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
            responseData.appendData(data)
        }

Below is the view for the Django form:

views.py

from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views.decorators.csrf import csrf_exempt

from myproject.myapp.models import Document
from myproject.myapp.forms import DocumentForm

@csrf_exempt
def list(request):
    # Handle file upload
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            newdoc = Document(docfile = request.FILES['docfile'])
            newdoc.save()

            # Redirect to the document list after POST
            return HttpResponse("Upload worked")
    else:
        form = DocumentForm() # A empty, unbound form

    # Render list page with the documents and the form
    return render_to_response(
        'upload.html',
        {'form': form},
        context_instance=RequestContext(request)
    )

And the Form I'm trying to save to looks like this when I ask Django to print it:

        <tr>
    <th>
        <label for=“id_docfile”>Select a file:</label>
    </th>
    <td>
        <input id=“id_docfile” name=“docfile” type=“file” />
    </td>
</tr>
Community
  • 1
  • 1
sech16
  • 11
  • 3

0 Answers0