Skip to content

Instantly share code, notes, and snippets.

@alexd1971
Created November 24, 2017 09:03
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save alexd1971/67f4502c5e0d594d30f901fb0559fd7e to your computer and use it in GitHub Desktop.
Save alexd1971/67f4502c5e0d594d30f901fb0559fd7e to your computer and use it in GitHub Desktop.
Dart file upload
import 'dart:async';
import 'dart:io';
import 'package:mime/mime.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf_rest/shelf_rest.dart';
class Api {
@Post('upload')
Future upload(shelf.Request request) async {
var header = HeaderValue.parse(request.headers['content-type']);
await for(MimeMultipart part in request.read().transform(new MimeMultipartTransformer(header.parameters['boundary']))) {
if(part.headers.containsKey('content-disposition')) {
header = HeaderValue.parse(part.headers['content-disposition']);
String filename = header.parameters['filename'];
final file = new File(filename);
IOSink fileSink = file.openWrite();
await part.pipe(fileSink);
fileSink.close();
}
}
return 'Ok';
}
}
import 'dart:async';
import 'dart:html';
import 'package:angular/angular.dart';
/// AngularDart component for uploading files
@Component(
selector: 'file-uploader',
styleUrls: const ['file_uploader.css'],
templateUrl: 'file_uploader.html',
directives: const [
CORE_DIRECTIVES,
],
providers: const [],
)
class FileUploader {
String progress;
void uploadFiles(form) {
var formData = new FormData(form);
final request = new HttpRequest();
request.open('POST', 'http://localhost:9999/api/upload');
request.upload.onProgress.listen((ProgressEvent e) {
progress = (e.loaded*100/e.total).toInt().toString() + '%';
});
request.onLoad.listen((e) {
print('Uploaded');
});
request.send(formData);
}
}
<div>
<form #form enctype="multipart/form-data">
<input type="file" #upload name='file' (change)="uploadFiles(form)">
</form>
<span>{{progress}}</span>
</div>
import 'dart:io';
import 'package:args/args.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_cors/shelf_cors.dart';
import 'package:shelf_rest/shelf_rest.dart';
import 'api.dart';
void main(List<String> args) {
var parser = new ArgParser()
..addOption('port', abbr: 'p', defaultsTo: '8080');
var result = parser.parse(args);
var port = int.parse(result['port'], onError: (val) {
stdout.writeln('Could not parse port value "$val" into a number.');
exit(1);
});
final cors = createCorsHeadersMiddleware(
corsHeaders: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Expose-Headers': 'Authorization, Content-Type',
'Access-Control-Allow-Headers': 'Authorization, Origin, X-Requested-With, Content-Type, Accept',
'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE'
}
);
var apiRouter = router()..addAll(new Api(), path: 'api');
var handler = const shelf.Pipeline()
.addMiddleware(shelf.logRequests())
.addMiddleware(cors)
.addHandler(apiRouter.handler);
io.serve(handler, '0.0.0.0', port).then((server) {
print('Serving at http://${server.address.host}:${server.port}');
});
}
@zambetpentru
Copy link

Thanks for sharing the above, I cannot seem to get it to work on current versions of Dart.

Error:type 'MimeMultipartTransformer' is not a subtype of type 'StreamTransformer<Uint8List, MimeMultipart>' of 'streamTransformer'

in this line:
await for (MimeMultipart part in request.read().transform(new MimeMultipartTransformer(header.parameters['boundary']!))) {

After many different iterations the following does work but it very memory intensive with the Int arrays:

List dataBytes = [];
await for (var data in request.read()) {
dataBytes.addAll(data);
}

String fileExtension = '';
late File file;
final transformer = MimeMultipartTransformer(header.parameters['boundary']!);
final bodyStream = Stream.fromIterable([dataBytes]);
final parts = await transformer.bind(bodyStream).toList();
final part = parts[0];
if (part.headers.containsKey('content-disposition')) {
  header = HeaderValue.parse(part.headers['content-disposition']!);
  originalfilename = header.parameters['filename'];
  print('originalfilename:' + originalfilename!);
  fileExtension = p.extension(originalfilename);
  file = await File('/destination/filename.mp4')
      .create(recursive: true); //Up two levels and then down into ServerFiles directory
  final content = await part.toList();
  await file.writeAsBytes(content[0]);
 }

Do you have any ideas of what I could try?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment