0

I am trying to upload a file in Dart with this code

Reading the file

    dom.InputElement uploadInput = dom.querySelector('#upload');

    uploadInput.onChange.listen((dom.Event e) 
    {
        // read file content as dataURL
        final files = uploadInput.files;

        if (files.length == 1) 
        {
            final file = files[0];
            final reader = new dom.FileReader();

            reader.onLoad.listen((_) 
            {
                dataRequest('upload', reader.result);
            });

            reader.readAsDataUrl (file);
        }
    });

Sending the file

    Future<dom.HttpRequest> dataRequest (String path, dynamic data)
    {
        return dom.HttpRequest.request (path, method: "POST", 
               sendData: data);
    }

But I get this error

POST http://localhost:9090/upload 400 (Bad Request) :9090/upload:1
Instance of '_XMLHttpRequestProgressEvent'

STACKTRACE:
null

I receive it in Redstone like this

@app.Route("/upload", methods: const [app.POST], allowMultipartRequest: true)
@Encode()
upload(@app.Body(app.FORM) Map form) 
{
    var file = form["file"];
    print(file.filename);
    print(file.contentType);
    print(file.runtimeType);

    return new Resp()
        ..success = (file.filename != null);
}

Any ideas?

Cristian Garcia
  • 9,630
  • 6
  • 54
  • 75
  • Looks like a duplicate of http://stackoverflow.com/questions/13298140 – Günter Zöchbauer Jan 15 '15 at 19:02
  • I got part of my setup from there, fixed a few things since dart have changed since that answer, but the problem is this error. – Cristian Garcia Jan 15 '15 at 19:18
  • How do you handle the request on the server? Maybe you can get some more details about the cause there. – Günter Zöchbauer Jan 15 '15 at 19:22
  • I don't know Redstone but I would try to set a brakpoint on the server and check if the metod gets called. If possible change the datatype in the signature to dynamic (instead of Map) to orevent exceptions. What is `app.Form`? Maybe the data is not sent as formdata. – Günter Zöchbauer Jan 15 '15 at 19:47

1 Answers1

1

Dart: 1.9.1
Redstone: 0.5.21

Let's say you have the following html:

<!DOCTYPE html>

<html>
  <head>
    <title>send_file.html</title>
  </head>

  <body>   
    <form id="read">
      user: <input type="text" name='user' value='DefaultValue'>
      <input type="file" id="file" name="my_file"/> <br>

      <input type="button" id="whole_btn" value="Send whole form!"> &nbsp;&nbsp;&nbsp;
      <input type="button" id="specific_btn" value="Send specific values!">
    </form>

    <script type="application/dart" src="send_file.dart"></script>
  </body>
</html>

Redstone server file:

import 'dart:io';
import 'package:logging/logging.dart';
import 'package:redstone/server.dart' as app;
import 'package:shelf_static/shelf_static.dart';

@app.ErrorHandler(HttpStatus.NOT_FOUND)
handleNotFoundError() => app.redirect("not_found.html");

@app.Route('/post',methods: const [app.POST], allowMultipartRequest: true)
wholeFormPost(@app.Body(app.FORM) Map form) {
  var user = form['user'];
  var f = form['my_file'];
  print('user: $user \n file: \n ${f.content}');
}

@app.Route('/post1',methods: const [app.POST], allowMultipartRequest: true)
specificPost(@app.Body(app.FORM) Map form) {
  var specificField = form['specificField'];
  var f = form['my_file'];
  print('specificField: $specificField \n file: \n ${f.content}');
}

@app.Interceptor(r'/.*')
interceptor1() {
  if (app.request.method == 'OPTIONS') {
    app.response = app.response.change(headers: CORS);
    app.chain.interrupt();
  } else {
    app.chain.next(() {
      return app.response = app.response.change(headers: CORS );
    });
  }
}

Map CORS = {
  "Access-Control-Allow-Origin" : "*, ",
  "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
  "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Content-Disposition"
};

main() {
  app.setShelfHandler(createStaticHandler("/home/raz2/dartProjects_linux_1/PR5/cl2/lib",
                                          defaultDocument: 'send_file.html',
                                            serveFilesOutsidePath: true));

  app.setupConsoleLog(Level.ALL);
  app.start(address: "0.0.0.0", port: 8081);
}

The client dart file: send_file.dart

import 'dart:html';

class UploadFileEx {
  FormElement _readForm;
  InputElement _fileInput;
  File file;
  ButtonElement _wholeBtn;
  ButtonElement _specificBtn;

  UploadFileEx() {
    _readForm = document.querySelector('#read');
    _fileInput = 
        document.querySelector('#file')
        ..onChange.listen(_onFileInputChange);

    _wholeBtn = 
        document.querySelector('#whole_btn')
        ..onClick.listen((sendForm));

    _specificBtn = 
        document.querySelector('#specific_btn')
        ..onClick.listen((sendFileAndField));
  }

  _onFileInputChange(_) {
    file = _fileInput.files[0];
  }

  // Send the whole form
  void sendForm(_) {
    if(file == null) 
      return;

    FormData fd = new FormData(_readForm);

    HttpRequest req = new HttpRequest();
    req.open("POST", 'http://127.0.0.1:8081/post');
    req.send(fd);
  }

  // add my own field to FormData
  void sendFileAndField(_) {
    if(file == null) 
      return;

    FormData fd = new FormData();
    fd.append('specificField', 'Lalala');
    fd.appendBlob('my_file', file);

    HttpRequest req = new HttpRequest();
    req.open("POST",'http://127.0.0.1:8081/post1');
    req.send(fd);
  }

}

void main() {
  new UploadFileEx();
}

Should work. Check out this link for more info: Sending_forms_through_JavaScript

Raizul
  • 73
  • 4