61 lines
1.9 KiB
Dart
61 lines
1.9 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:client_proxy_framework/client_proxy_framework.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
/// PUT 到 [FeedbackApi.getUploadPresignedUrl] 返回的地址,返回服务端 [FeedbackUploadPresignedUrlResponse.filePath] 供 [FeedbackApi.submit] 的 `fileUrls`。
|
|
Future<String> uploadFeedbackAttachment(File file) async {
|
|
final name = file.path.split('/').last;
|
|
final presignedRes = await FeedbackApi.getUploadPresignedUrl(fileName: name);
|
|
if (!presignedRes.isSuccess || presignedRes.data == null) {
|
|
throw StateError(
|
|
presignedRes.msg.isNotEmpty
|
|
? presignedRes.msg
|
|
: 'Could not get upload URL',
|
|
);
|
|
}
|
|
final p = presignedRes.data!;
|
|
await ImageUploadExpectedSizeCache.writeFeedbackExpectedSize(p.expectedSize);
|
|
final uploadUrl = p.uploadUrl;
|
|
final filePath = p.filePath;
|
|
if (uploadUrl == null ||
|
|
uploadUrl.isEmpty ||
|
|
filePath == null ||
|
|
filePath.isEmpty) {
|
|
throw StateError('Invalid upload URL response');
|
|
}
|
|
|
|
final bytes = await file.readAsBytes();
|
|
final contentType = _mimeForPath(file.path);
|
|
final headers = <String, String>{'Content-Type': contentType};
|
|
final extra = p.putHeaders;
|
|
if (extra != null) {
|
|
for (final e in extra.entries) {
|
|
final k = e.key.trim();
|
|
if (k.isEmpty) continue;
|
|
headers[k] = e.value.toString();
|
|
}
|
|
}
|
|
if (!headers.containsKey('Content-Type')) {
|
|
headers['Content-Type'] = contentType;
|
|
}
|
|
|
|
final r = await http.put(
|
|
Uri.parse(uploadUrl),
|
|
headers: headers,
|
|
body: bytes,
|
|
);
|
|
if (r.statusCode < 200 || r.statusCode >= 300) {
|
|
throw StateError('Upload failed (${r.statusCode})');
|
|
}
|
|
return filePath;
|
|
}
|
|
|
|
String _mimeForPath(String path) {
|
|
final lower = path.toLowerCase();
|
|
if (lower.endsWith('.png')) return 'image/png';
|
|
if (lower.endsWith('.gif')) return 'image/gif';
|
|
if (lower.endsWith('.webp')) return 'image/webp';
|
|
return 'image/jpeg';
|
|
}
|