[Dart] Flutter 上传文件
/** * 请求响应数据 */ class MsgResponse { int code; // 状态代码,0 表示没有错误 Object data; // 数据内容,一般为字符串 String errmsg; // 错误消息 MsgResponse([this.code = 0, this.data = null, this.errmsg = ""]); } static Map _makeHttpHeaders( [String contentType, String accept, String token, String XRequestWith, String XMethodOverride]) { Map headers = new Map<String, String>(); int i = 0; if (!strIsEmpty(contentType)) { i++; headers["Content-Type"] = contentType; } if (!strIsEmpty(accept)) { i++; headers["Accept"] = accept; } if (!strIsEmpty(token)) { i++; headers["Authorization"] = "bearer " + token; } if (!strIsEmpty(XRequestWith)) { i++; headers["X-Requested-With"] = XRequestWith; } if (!strIsEmpty(XMethodOverride)) { i++; headers["X-HTTP-Method-Override"] = XMethodOverride; } if (i == 0) return null; // print(headers.toString()); return headers; } /** HTTP POST 上传文件 */ static Future<MsgResponse> httpUploadFile( final String url, final File file, { String accept = "*/*", String token, String field = "picture-upload", String file_contentType, // 默认为null,自动获取 }) async { try { List<int> bytes = await file.readAsBytes(); return await httpUploadFileData(url, bytes, accept: accept, token: token, field: field, file_contentType: file_contentType, filename: file.path); } catch (e) { return new MsgResponse(699, null, e.toString()); } } /** HTTP POST 上传文件 */ static Future<MsgResponse> httpUploadFileData( final String url, final List<int> filedata, { String accept = "*/*", String token, String field = "picture-upload", String file_contentType, // 默认为null,自动获取 String filename, }) async { try { List<int> bytes = filedata; var boundary = _boundaryString(); String contentType = 'multipart/form-data; boundary=$boundary'; Map headers = _makeHttpHeaders(contentType, accept, token); //, "XMLHttpRequest"); // 构造文件字段数据 String data = '--$boundary\r\nContent-Disposition: form-data; name="$field"; ' + 'filename="${getFileFullName(filename)}"\r\nContent-Type: ' + '${(file_contentType == null) ? getMediaType(getFileExt(filename).toLowerCase()): file_contentType}\r\n\r\n'; var controller = new StreamController<List<int>>(sync: true); controller.add(data.codeUnits); controller.add(bytes); controller.add("\r\n--$boundary--\r\n".codeUnits); controller.close(); bytes = await new Http.ByteStream(controller.stream).toBytes(); //print("bytes: \r\n" + UTF8.decode(bytes, allowMalformed: true)); Http.Response response = await Http.post(url, headers: headers, body: bytes); if (response.statusCode == 200) { return new MsgResponse(0, response.body); } else return new MsgResponse(response.statusCode, response.body); } catch (e) { return new MsgResponse(699, null, e.toString()); } } /** 生成随机字符串 */ static String randomStr( [int len = 8, List<int> chars = _BOUNDARY_CHARACTERS]) { var list = new List<int>.generate( len, (index) => chars[_random.nextInt(chars.length)], growable: false); return new String.fromCharCodes(list); } static const List<int> _BOUNDARY_CHARACTERS = const <int>[ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A ]; static const int _BOUNDARY_LENGTH = 48; static final Random _random = new Random(); static String _boundaryString() { var prefix = "---DartFormBoundary"; var list = new List<int>.generate( _BOUNDARY_LENGTH - prefix.length, (index) => _BOUNDARY_CHARACTERS[_random.nextInt(_BOUNDARY_CHARACTERS.length)], growable: false); return "$prefix${new String.fromCharCodes(list)}"; } static MediaType getMediaType(final String fileExt) { switch (fileExt) { case ".jpg": case ".jpeg": case ".jpe": return new MediaType("image", "jpeg"); case ".png": return new MediaType("image", "png"); case ".bmp": return new MediaType("image", "bmp"); case ".gif": return new MediaType("image", "gif"); case ".json": return new MediaType("application", "json"); case ".svg": case ".svgz": return new MediaType("image", "svg+xml"); case ".mp3": return new MediaType("audio", "mpeg"); case ".mp4": return new MediaType("video", "mp4"); case ".htm": case ".html": return new MediaType("text", "html"); case ".css": return new MediaType("text", "css"); case ".csv": return new MediaType("text", "csv"); case ".txt": case ".text": case ".conf": case ".def": case ".log": case ".in": return new MediaType("text", "plain"); } return null; }