upload_controller.dart 2.51 KB
Newer Older
1
2
import 'dart:io';

Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
3
import 'package:aqueduct/aqueduct.dart';
4
5
import 'package:mime/mime.dart';

Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
6
7
import '../coupons_backend.dart';

8
9
10
11
12
13
14
const Map<List<int>, String> supportedTypes = <List<int>, String>{
  [0xFF, 0xD8]: 'image/jpeg',
  [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]: 'image/png',
  [0x47, 0x49, 0x46, 0x38]: 'image/gif',
  [0x42, 0x4D]: 'image/bmp',
};

Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
15
class UploadController extends ResourceController {
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
16
  UploadController() {
17
18
19
20
21
    mimeChecker = MimeTypeResolver();
    supportedTypes.forEach(mimeChecker.addMagicNumber);
    acceptedContentTypes = supportedTypes.values
        .map((String e) => ContentType(e.split('/').first, e.split('/').last))
        .toList();
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
22
23
  }

24
25
  MimeTypeResolver mimeChecker;

Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
26
27
28
  @Operation.get()
  Future<Response> getFiles() async {
    final assetsDir = Directory('assets');
29
30
    final files = <String>[];
    await assetsDir
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
31
32
        .list(recursive: true, followLinks: false)
        .listen((FileSystemEntity entity) {
33
      files.add(entity.path.split(Platform.pathSeparator).last);
34
    }).asFuture();
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
35

36
37
    files.sort();

Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
38
    return Response.ok(files.toString());
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
39
40
41
  }

  @Operation.post()
42
43
44
45
46
47
  Future<Response> postFile() async {
    const assetsFolderPath = 'assets';
    var filename = '${DateTime.now().millisecondsSinceEpoch}';
    final newFilePath = '$assetsFolderPath${Platform.pathSeparator}$filename';

    // read response and write to file
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
48
    final bodyBytes = await request.body.decode<List<int>>();
49
50
51
52
53
54
55
56
    final contentType = request.raw.headers['Content-Type'].single;
    var file = await File(newFilePath).writeAsBytes(bodyBytes);

    final mimeType =
        mimeChecker.lookup(file.path, headerBytes: bodyBytes.take(8).toList());

    // check mimetype and append suffix to filename
    if (contentType == null || mimeType != contentType) {
57
      await file.delete();
58
59
60
61
62
63
64
65
66
67
      return Response.badRequest(
          body: 'content-type not given or inconsistent with file');
    }

    try {
      filename += '.${acceptedContentTypes.singleWhere((ContentType type) {
            print('${type.mimeType} == $contentType');
            return type.mimeType == contentType;
          }).mimeType.split('/').last}';
    } catch (e) {
68
      await file.delete();
69
70
71
72
73
74
75
      return Response.badRequest(body: e.toString());
    }

    file = await file
        .rename('$assetsFolderPath${Platform.pathSeparator}$filename');

    // return name if file was successfully renamed
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
76
77
78
    if (file.existsSync()) {
      return Response.ok(filename);
    } else {
79
      await file.delete();
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
80
81
      return Response.noContent();
    }
Daniel Ravi Negi's avatar
Daniel Ravi Negi committed
82
83
  }
}