Flutter Dio:如何上传图片?
Flutter Dio : How to Upload Image?
我正在试用 Postman。它有效
我想使用 Package DIO Package 将一些图像上传到 rest-api ,
我是这个包的新手(我只是将这个包用于 CRUD 操作)并且在上传图像操作时遇到问题。
我已经在阅读文档,但没有看到上传图片。我正在尝试此代码(参考文档)并出现一些错误:
error:FileSystemException
message :"Cannot retrieve length of file"
OSError (OS Error: No such file or directory, errno = 2)
"File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'"
Type (FileSystemException)
message:FileSystemException: Cannot retrieve length of file, path = 'File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'' (OS Error: No such file or directory, errno = 2)
DioErrorType (DioErrorType.DEFAULT)
name:"DioErrorType.DEFAULT"
Api.dart
Future uploadImage({dynamic data,Options options}) async{
Response apiRespon = await dio.post('$baseURL/mahasiswa/upload/',data: data,options: options);
if(apiRespon.statusCode== 201){
return apiRespon.statusCode==201;
}else{
print('errr');
return null;
}
}
View.dart
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
_image is type FILE
我希望这个软件包的专家可以帮助我处理这段代码并建议我上传图片。
谢谢。
完整View.dart代码
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mosque/api/api_mosque.dart';
class UploadImage extends StatefulWidget {
@override
_UploadImageState createState() => _UploadImageState();
}
class _UploadImageState extends State<UploadImage> {
ApiHelper api = ApiHelper();
File _image;
TextEditingController _txtNameImage = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_left),
onPressed: () => Navigator.pop(context, false),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.file_upload),
onPressed: () {
uploadImage();
},
)
],
),
body: _formUpload(),
);
}
Widget _formUpload() {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: <Widget>[
TextField(
controller: _txtNameImage,
keyboardType: TextInputType.text,
decoration: InputDecoration(hintText: "Nama Image"),
maxLength: 9,
textAlign: TextAlign.center,
),
SizedBox(
height: 50.0,
),
Container(
child: _image == null
? Text('No Images Selected')
: Image.file(_image),
),
SizedBox(
height: 50.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(Icons.camera),
onPressed: () => getImageCamera(),
),
SizedBox(
width: 50.0,
),
RaisedButton(
child: Icon(Icons.image),
onPressed: () => getImageGallery(),
)
],
)
],
),
);
}
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
getImageGallery() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = imageFile;
});
}
getImageCamera() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = imageFile;
});
}
}
如果您正在处理内存图像,请使用 UploadFileInfo.fromBytes
(上面的错误消息表明您的文件无效且不存在)。
您好,文件上传有很多问题
尝试 android Api 21 因为它没有 android 权限如果 api 在 android api 21 那么它也适用于以上版本。
您可能无法获取 android 以上版本的文件
你只需要
FormData formData = FormData.fromMap({
"av_document": 等待 MultipartFile.fromFile(_filePath,文件名:
_文件名),
});
上传任何文件或图片到服务器还有一件事要注意
_filePaths = await FilePicker.getMultiFilePath(type: _pickingType,
fileExtension: _extension);
_fileName = _filePath.split('/').last
通过使用此过程,您可以将文件或图像上传到服务器
在Dio最新版本中,UploadFileInfo
方法已被MultipartFile
class取代。这里是如何使用 post 图片、视频或任何文件的方法:
Future<String> uploadImage(File file) async {
String fileName = file.path.split('/').last;
FormData formData = FormData.fromMap({
"file":
await MultipartFile.fromFile(file.path, filename:fileName),
});
response = await dio.post("/info", data: formData);
return response.data['id'];
}
即使这个问题是前一段时间提出的,我认为主要问题是图像的 size
,尤其是 Laravel
。Flutter Image Picker 库提供了一些功能来减小图像的大小图片,我用下面的步骤解决了它:
创建一个获取图像的方法,我正在使用Camera
来捕获照片
Future getImage() async {
File _image;
final picker = ImagePicker();
var _pickedFile = await picker.getImage(
source: ImageSource.camera,
imageQuality: 50, // <- Reduce Image quality
maxHeight: 500, // <- reduce the image size
maxWidth: 500);
_image = _pickedFile.path;
_upload(_image);
}
创建_upload
方法上传照片,我用的是Dio
包Dio Package
void _upload(File file) async {
String fileName = file.path.split('/').last;
FormData data = FormData.fromMap({
"file": await MultipartFile.fromFile(
file.path,
filename: fileName,
),
});
Dio dio = new Dio();
dio.post("http://192.168.43.225/api/media", data: data)
.then((response) => print(response))
.catchError((error) => print(error));
}
在服务器端,我使用Laravel
Laravel,我处理请求如下
public function store(Request $request)
{
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$fullFileName = time(). '.'. $extension;
$file->storeAs('uploads', $fullFileName, ['disk' => 'local']);
return 'uploaded Successfully';
}
以下代码将多个图像文件从 dio 客户端上传到 golang 服务器。
- dioclient.dart
FormData formData = FormData.fromMap({
"name": "wendux",
"age": 25,
"other" : "params",
});
for (File item in yourFileList)
formData.files.addAll([
MapEntry("image_files", await MultipartFile.fromFile(item.path)),
]);
Dio dio = new Dio()..options.baseUrl = "http://serverURL:port";
dio.post("/uploadFile", data: formData).then((response) {
print(response);
}).catchError((error) => print(error));
- golangServer.go
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func uploadFile(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(200000)
if err != nil {
fmt.Fprintln(w, err)
return
}
formdata := r.MultipartForm
files := formdata.File["image_files"]
for i, _ := range files {
file, err := files[i].Open()
defer file.Close()
if err != nil {
fmt.Fprintln(w, err)
return
}
out, err := os.Create("/path/to/dir/" + files[i].Filename)
defer out.Close()
if err != nil {
fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
return
}
_, err = io.Copy(out, file)
if err != nil {
fmt.Fprintln(w, err)
return
}
fmt.Fprintf(w, "Files uploaded successfully : ")
fmt.Fprintf(w, files[i].Filename+"\n")
}
}
func startServer() {
http.HandleFunc("/uploadFile", uploadFile)
http.ListenAndServe(":9983", nil)
}
func main() {
fmt.Println("Server starts!")
startServer()
}
在最新版本的Dio中:
它应该是这样的。
String fileName = imageFile.path.split('/').last;
FormData formData = FormData.fromMap({
"image-param-name": await MultipartFile.fromFile(
imageFile.path,
filename: fileName,
contentType: new MediaType("image", "jpeg"), //important
),
});
如果没有这条线。
contentType: new MediaType("image", "jpeg")
可能会报错:DioError [DioErrorType.RESPONSE]: Http status error [400] Exception
并在这个包中得到 MediaType
:http_parser
我找到了一个解决方案,我将文件上传到特定目录,该目录生成不同的相机包,需要文件路径才能将 jpg 文件保存在提供的路径中。
我正在获取带有路径的文件名并传递给
DIO package
这是一个文件长度问题,我已经实施了以下步骤来解决这个问题
从目录中获取完整路径的文件名
从路径创建一个文件
File(directoryFilePathWithExtension);
并将File.path传给dio包
MultipartFile.fromFile(
File(directoryFilePathWithExtension).path,
filename: DateTime.now().toIso8601String(),
)
我正在试用 Postman。它有效
我已经在阅读文档,但没有看到上传图片。我正在尝试此代码(参考文档)并出现一些错误:
error:FileSystemException
message :"Cannot retrieve length of file"
OSError (OS Error: No such file or directory, errno = 2)
"File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'"
Type (FileSystemException)
message:FileSystemException: Cannot retrieve length of file, path = 'File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'' (OS Error: No such file or directory, errno = 2)
DioErrorType (DioErrorType.DEFAULT)
name:"DioErrorType.DEFAULT"
Api.dart
Future uploadImage({dynamic data,Options options}) async{
Response apiRespon = await dio.post('$baseURL/mahasiswa/upload/',data: data,options: options);
if(apiRespon.statusCode== 201){
return apiRespon.statusCode==201;
}else{
print('errr');
return null;
}
}
View.dart
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
_image is type FILE
我希望这个软件包的专家可以帮助我处理这段代码并建议我上传图片。
谢谢。
完整View.dart代码
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mosque/api/api_mosque.dart';
class UploadImage extends StatefulWidget {
@override
_UploadImageState createState() => _UploadImageState();
}
class _UploadImageState extends State<UploadImage> {
ApiHelper api = ApiHelper();
File _image;
TextEditingController _txtNameImage = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_left),
onPressed: () => Navigator.pop(context, false),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.file_upload),
onPressed: () {
uploadImage();
},
)
],
),
body: _formUpload(),
);
}
Widget _formUpload() {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: <Widget>[
TextField(
controller: _txtNameImage,
keyboardType: TextInputType.text,
decoration: InputDecoration(hintText: "Nama Image"),
maxLength: 9,
textAlign: TextAlign.center,
),
SizedBox(
height: 50.0,
),
Container(
child: _image == null
? Text('No Images Selected')
: Image.file(_image),
),
SizedBox(
height: 50.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(Icons.camera),
onPressed: () => getImageCamera(),
),
SizedBox(
width: 50.0,
),
RaisedButton(
child: Icon(Icons.image),
onPressed: () => getImageGallery(),
)
],
)
],
),
);
}
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
getImageGallery() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = imageFile;
});
}
getImageCamera() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = imageFile;
});
}
}
如果您正在处理内存图像,请使用 UploadFileInfo.fromBytes
(上面的错误消息表明您的文件无效且不存在)。
您好,文件上传有很多问题
尝试 android Api 21 因为它没有 android 权限如果 api 在 android api 21 那么它也适用于以上版本。
您可能无法获取 android 以上版本的文件
你只需要
FormData formData = FormData.fromMap({ "av_document": 等待 MultipartFile.fromFile(_filePath,文件名: _文件名), });
上传任何文件或图片到服务器还有一件事要注意
_filePaths = await FilePicker.getMultiFilePath(type: _pickingType,
fileExtension: _extension);
_fileName = _filePath.split('/').last
通过使用此过程,您可以将文件或图像上传到服务器
在Dio最新版本中,UploadFileInfo
方法已被MultipartFile
class取代。这里是如何使用 post 图片、视频或任何文件的方法:
Future<String> uploadImage(File file) async {
String fileName = file.path.split('/').last;
FormData formData = FormData.fromMap({
"file":
await MultipartFile.fromFile(file.path, filename:fileName),
});
response = await dio.post("/info", data: formData);
return response.data['id'];
}
即使这个问题是前一段时间提出的,我认为主要问题是图像的 size
,尤其是 Laravel
。Flutter Image Picker 库提供了一些功能来减小图像的大小图片,我用下面的步骤解决了它:
创建一个获取图像的方法,我正在使用
Camera
来捕获照片Future getImage() async { File _image; final picker = ImagePicker(); var _pickedFile = await picker.getImage( source: ImageSource.camera, imageQuality: 50, // <- Reduce Image quality maxHeight: 500, // <- reduce the image size maxWidth: 500); _image = _pickedFile.path; _upload(_image); }
创建
_upload
方法上传照片,我用的是Dio
包Dio Packagevoid _upload(File file) async { String fileName = file.path.split('/').last; FormData data = FormData.fromMap({ "file": await MultipartFile.fromFile( file.path, filename: fileName, ), }); Dio dio = new Dio(); dio.post("http://192.168.43.225/api/media", data: data) .then((response) => print(response)) .catchError((error) => print(error)); }
在服务器端,我使用
Laravel
Laravel,我处理请求如下public function store(Request $request) { $file = $request->file('file'); $extension = $file->getClientOriginalExtension(); $fullFileName = time(). '.'. $extension; $file->storeAs('uploads', $fullFileName, ['disk' => 'local']); return 'uploaded Successfully'; }
以下代码将多个图像文件从 dio 客户端上传到 golang 服务器。
- dioclient.dart
FormData formData = FormData.fromMap({ "name": "wendux", "age": 25, "other" : "params", }); for (File item in yourFileList) formData.files.addAll([ MapEntry("image_files", await MultipartFile.fromFile(item.path)), ]); Dio dio = new Dio()..options.baseUrl = "http://serverURL:port"; dio.post("/uploadFile", data: formData).then((response) { print(response); }).catchError((error) => print(error));
- golangServer.go
package main import ( "fmt" "io" "net/http" "os" ) func uploadFile(w http.ResponseWriter, r *http.Request) { err := r.ParseMultipartForm(200000) if err != nil { fmt.Fprintln(w, err) return } formdata := r.MultipartForm files := formdata.File["image_files"] for i, _ := range files { file, err := files[i].Open() defer file.Close() if err != nil { fmt.Fprintln(w, err) return } out, err := os.Create("/path/to/dir/" + files[i].Filename) defer out.Close() if err != nil { fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege") return } _, err = io.Copy(out, file) if err != nil { fmt.Fprintln(w, err) return } fmt.Fprintf(w, "Files uploaded successfully : ") fmt.Fprintf(w, files[i].Filename+"\n") } } func startServer() { http.HandleFunc("/uploadFile", uploadFile) http.ListenAndServe(":9983", nil) } func main() { fmt.Println("Server starts!") startServer() }
在最新版本的Dio中:
它应该是这样的。
String fileName = imageFile.path.split('/').last;
FormData formData = FormData.fromMap({
"image-param-name": await MultipartFile.fromFile(
imageFile.path,
filename: fileName,
contentType: new MediaType("image", "jpeg"), //important
),
});
如果没有这条线。
contentType: new MediaType("image", "jpeg")
可能会报错:DioError [DioErrorType.RESPONSE]: Http status error [400] Exception
并在这个包中得到 MediaType
:http_parser
我找到了一个解决方案,我将文件上传到特定目录,该目录生成不同的相机包,需要文件路径才能将 jpg 文件保存在提供的路径中。
我正在获取带有路径的文件名并传递给
DIO package
这是一个文件长度问题,我已经实施了以下步骤来解决这个问题
从目录中获取完整路径的文件名 从路径创建一个文件
File(directoryFilePathWithExtension);
并将File.path传给dio包
MultipartFile.fromFile(
File(directoryFilePathWithExtension).path,
filename: DateTime.now().toIso8601String(),
)