您好,我正在尝试创建一个非常基本的flutter应用程序,该应用程序将从我的桌面上拍摄一张照片,然后通过HTTP.POST(作为一个多部分文件)将其发送到我的服务器。我一直在使用dio
尝试此操作,但是由于某种原因,我的服务器一直在声明该'image' is not present
。我尝试调试邮政编码,该图像显示在日志中(base64等)。我在PostMan中尝试了此方法,并获得了成功,尽管随风而动,我得到POST http://localhost:8080/event/test 500
的话说Required request part 'image' is not present
。
这是我尝试使用的图像:
这是我测试过的一些数据为null或无效,并且在创建FormData之后似乎又恢复为有效:
print(formData.fields.last.key); // image
print(formData.fields.last.value); // Instance of 'MultipartFile'
print(formData.fields.last.value.length); // 27
print(formData.fields.last.value.isEmpty); // false
这是我的颤动代码:
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:file_picker_cross/file_picker_cross.dart';
import 'package:flutter/material.dart';
import 'package:http_parser/http_parser.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
FilePickerCross filePickerCross;
String _fileString = '';
Set<String> lastFiles;
FileQuotaCross quota = FileQuotaCross(quota: 0, usage: 0);
@override
void initState() {
FilePickerCross.listInternalFiles()
.then((value) => setState(() => lastFiles = value.toSet()));
FilePickerCross.quota().then((value) => setState(() => quota = value));
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.blueGrey, accentColor: Colors.lightGreen),
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: ListView(
padding: EdgeInsets.all(8),
children: <Widget>[
Text(
'Last files',
style: Theme.of(context).textTheme.headline5,
),
(lastFiles == null)
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
shrinkWrap: true,
primary: false,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => ListTile(
leading: Text('$index.'),
title: Text(lastFiles.toList()[index]),
onTap: () async => setFilePicker(
await FilePickerCross.fromInternalPath(
path: lastFiles.toList()[index])),
),
itemCount: lastFiles.length,
),
RaisedButton(
onPressed: _selectFile,
child: Text('Open File...'),
),
(filePickerCross == null)
? Text('Open a file first, to save')
: RaisedButton(
onPressed: _selectSaveFile,
child: Text('Save as...'),
),
Text(
'File system details',
style: Theme.of(context).textTheme.headline5,
),
Text('Quota: ${(quota.quota / 1e6).round()} MB'),
Text(
'Usage: ${(quota.usage / 1e6).round()}; Remaining: ${(quota.remaining / 1e6).round()}'),
Text('Percentage: ${quota.relative.roundToDouble()}'),
Text(
'File details',
style: Theme.of(context).textTheme.headline5,
),
Text(
'File path: ${filePickerCross?.path ?? 'unknown'} (Might cause issues on web)\n'),
Text('File length: ${filePickerCross?.length ?? 0}\n'),
Text('File as String: $_fileString\n'),
],
),
),
);
}
void _selectFile() {
FilePickerCross.importFromStorage()
.then((filePicker) => setFilePicker(filePicker));
}
void _selectSaveFile() {
filePickerCross.exportToStorage();
}
setFilePicker(FilePickerCross filePicker) => setState(() {
filePickerCross = filePicker;
filePickerCross.saveToPath(path: filePickerCross.fileName);
FilePickerCross.quota().then((value) {
print(value);
setState(() => quota = value);
});
lastFiles.add(filePickerCross.fileName);
try {
_fileString = filePickerCross.toString();
} catch (e) {
_fileString = 'Not a text file. Showing base64.\n\n' +
filePickerCross.toBase64();
Upload(filePickerCross);
}
});
Future<void> Upload(FilePickerCross file) async {
Dio dio = new Dio();
try{
FormData formData = new FormData.fromMap({"image":
file.toMultipartFile()});
print(formData.fields.last.key);
print(formData.fields.last.value);
print(formData.fields.last.value.length);
print(formData.fields.last.value.isEmpty);
Response response = await dio.post("http://localhost:8080/event/test",data:formData, options: Options(
headers: {
"accept" : "*/*",
// "Authorization" : "TOKEN",
"Content-Type" : "multipart/form-data",
}
));
print(response);
print("d");
}catch(e){
}
}
}
这就是我对邮递员的厌倦:
最后这是我的服务器代码:
@PostMapping(value = "/test")
@ApiOperation(value = "add an event data via the body ")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = ResponseModel.class)})
public ResponseEntity<?> post(@RequestPart("image") MultipartFile image) {
ResponseModel responseModel;
System.out.println(image.getName());
int responseNumber = 0;
String res = response(responseNumber);
if (responseNumber != 0) {
responseModel = new ResponseModel(false, responseNumber, res);
} else {
responseModel = new ResponseModel(true, responseNumber, res);
}
return new ResponseEntity<>( responseModel, HttpStatus.OK);
}
答案 0 :(得分:0)
因此,您需要实施一些稍微不同的网络,请参见下文:
Future<String> makeRequest() async {
var url = Uri.parse(
"http://localhost:8080/event/");
var request = new http.MultipartRequest("POST", url);
EventResource eventResource = new EventResource();
//Created and added values to eventResource
var body = jsonEncode(eventResource);
request.files.add(await http.MultipartFile.fromBytes('image', _selectedFile,
contentType: new MediaType('application', 'octet-stream'),
filename: name));
request.files.add(await http.MultipartFile.fromString('body', body,
contentType: new MediaType('application', 'json'),
));
request.headers['Content-Type'] = "application/json";
request.headers['Authorization'] = "SOME_JWT";
request.send().then((response) {
print(response.statusCode);
});