pdf查看
This commit is contained in:
@@ -3,12 +3,14 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_pdfview/flutter_pdfview.dart';
|
||||
import 'package:getx_scaffold/getx_scaffold.dart' as dio;
|
||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:ln_jq_app/common/model/base_model.dart';
|
||||
import 'package:ln_jq_app/common/styles/theme.dart';
|
||||
import 'package:ln_jq_app/storage_service.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:photo_view/photo_view_gallery.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
@@ -794,54 +796,83 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
}
|
||||
|
||||
/// 保存图片到相册
|
||||
Future<void> saveImageToLocal(String url) async {
|
||||
// 1. 权限请求
|
||||
if (Platform.isAndroid) {
|
||||
dio.PermissionStatus status;
|
||||
Future<void> saveFileToLocal(String url) async {
|
||||
try {
|
||||
// 权限请求
|
||||
if (Platform.isAndroid) {
|
||||
dio.PermissionStatus status;
|
||||
|
||||
final deviceInfo = await DeviceInfoPlugin().androidInfo;
|
||||
final sdkInt = deviceInfo.version.sdkInt;
|
||||
final deviceInfo = await DeviceInfoPlugin().androidInfo;
|
||||
final sdkInt = deviceInfo.version.sdkInt;
|
||||
|
||||
if (sdkInt <= 32) {
|
||||
status = await Permission.storage.request();
|
||||
if (sdkInt <= 32) {
|
||||
status = await Permission.storage.request();
|
||||
} else {
|
||||
status = await Permission.photos.request();
|
||||
}
|
||||
|
||||
if (!status.isGranted) {
|
||||
showErrorToast("请在系统设置中开启存储权限");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
status = await Permission.photos.request();
|
||||
var status = await Permission.photos.request();
|
||||
if (!status.isGranted) {
|
||||
showErrorToast("请在系统设置中开启相册权限");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!status.isGranted) {
|
||||
showErrorToast("请在系统设置中开启存储权限");
|
||||
return;
|
||||
showLoading("正在保存...");
|
||||
|
||||
// 下载文件
|
||||
var response = await Dio().get(
|
||||
url,
|
||||
options: Options(responseType: ResponseType.bytes),
|
||||
);
|
||||
|
||||
final Uint8List bytes = Uint8List.fromList(response.data);
|
||||
|
||||
if (url.toLowerCase().endsWith('.pdf')) {
|
||||
String? savePath;
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
final directory = Directory('/storage/emulated/0/Download');
|
||||
if (!await directory.exists()) {
|
||||
await directory.create(recursive: true);
|
||||
}
|
||||
final String fileName = "certificate_${DateTime.now().millisecondsSinceEpoch}.pdf";
|
||||
savePath = "${directory.path}/$fileName";
|
||||
} else {
|
||||
// iOS: 保存到文档目录
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
final String fileName = "certificate_${DateTime.now().millisecondsSinceEpoch}.pdf";
|
||||
savePath = "${directory.path}/$fileName";
|
||||
}
|
||||
|
||||
final File file = File(savePath);
|
||||
await file.writeAsBytes(bytes);
|
||||
|
||||
dismissLoading();
|
||||
showSuccessToast(Platform.isAndroid ? "PDF已保存至系统下载目录" : "PDF已保存,请在'文件'App中查看");
|
||||
} else {
|
||||
// 保存图片到相册
|
||||
final result = await SaverGallery.saveImage(
|
||||
bytes,
|
||||
quality: 100,
|
||||
fileName: "certificate_${DateTime.now().millisecondsSinceEpoch}",
|
||||
skipIfExists: false,
|
||||
);
|
||||
dismissLoading();
|
||||
if (result.isSuccess) {
|
||||
showSuccessToast("图片已保存至相册");
|
||||
} else {
|
||||
showErrorToast("保存失败");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var status = await Permission.photos.request();
|
||||
if (!status.isGranted) {
|
||||
showErrorToast("请在系统设置中开启相册权限");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
showLoading("正在保存...");
|
||||
|
||||
// 2. 下载图片
|
||||
var response = await Dio().get(
|
||||
url,
|
||||
options: Options(responseType: ResponseType.bytes),
|
||||
);
|
||||
|
||||
// 3. 保存到相册
|
||||
final result = await SaverGallery.saveImage(
|
||||
Uint8List.fromList(response.data),
|
||||
quality: 100,
|
||||
fileName: "certificate_${DateTime.now().millisecondsSinceEpoch}",
|
||||
skipIfExists: false,
|
||||
);
|
||||
|
||||
dismissLoading();
|
||||
|
||||
if (result.isSuccess) {
|
||||
showSuccessToast("图片已保存至相册");
|
||||
} else {
|
||||
showErrorToast("保存失败");
|
||||
} catch (e) {
|
||||
dismissLoading();
|
||||
showErrorToast("保存异常");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,12 +919,30 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
child: PhotoViewGallery.builder(
|
||||
scrollPhysics: const BouncingScrollPhysics(),
|
||||
builder: (BuildContext context, int index) {
|
||||
final String url = images[index];
|
||||
final bool isPdf = url.toLowerCase().endsWith('.pdf');
|
||||
|
||||
if (isPdf) {
|
||||
return PhotoViewGalleryPageOptions.customChild(
|
||||
child: GestureDetector(
|
||||
onTap: (){
|
||||
_showSaveMenu(url);
|
||||
},
|
||||
child: _buildPdfPreview(url),),
|
||||
initialScale: PhotoViewComputedScale.contained,
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: url),
|
||||
onTapDown: (context, details, controllerValue) {
|
||||
_showSaveMenu(url);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return PhotoViewGalleryPageOptions(
|
||||
imageProvider: NetworkImage(images[index]),
|
||||
imageProvider: NetworkImage(url),
|
||||
initialScale: PhotoViewComputedScale.contained,
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: images[index]),
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: url),
|
||||
onTapDown: (context, details, controllerValue) {
|
||||
_showSaveImageMenu(images[index]);
|
||||
_showSaveMenu(url);
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -939,7 +988,38 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
);
|
||||
}
|
||||
|
||||
void _showSaveImageMenu(String url) {
|
||||
/// PDF 预览小部件
|
||||
Widget _buildPdfPreview(String url) {
|
||||
return FutureBuilder<String>(
|
||||
future: _downloadPdf(url),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator(color: Colors.white));
|
||||
}
|
||||
if (snapshot.hasError || snapshot.data == null) {
|
||||
return const Center(child: Text("PDF 加载失败", style: TextStyle(color: Colors.white)));
|
||||
}
|
||||
return PDFView(
|
||||
filePath: snapshot.data!,
|
||||
enableSwipe: false,
|
||||
swipeHorizontal: false,
|
||||
autoSpacing: false,
|
||||
pageFling: false,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> _downloadPdf(String url) async {
|
||||
final file = File('${(await getTemporaryDirectory()).path}/${url.hashCode}.pdf');
|
||||
if (await file.exists()) return file.path;
|
||||
var response = await Dio().get(url, options: Options(responseType: ResponseType.bytes));
|
||||
await file.writeAsBytes(response.data);
|
||||
return file.path;
|
||||
}
|
||||
|
||||
void _showSaveMenu(String url) {
|
||||
final bool isPdf = url.toLowerCase().endsWith('.pdf');
|
||||
Get.bottomSheet(
|
||||
Container(
|
||||
color: Colors.white,
|
||||
@@ -949,10 +1029,10 @@ class SiteController extends GetxController with BaseControllerMixin {
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.download),
|
||||
title: const Text('保存图片到相册'),
|
||||
title: Text(isPdf ? '保存 PDF 文件' : '保存图片到相册'),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
saveImageToLocal(url);
|
||||
saveFileToLocal(url);
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
|
||||
Reference in New Issue
Block a user