1use super::{File, UploadedFile};
57
58#[derive(Debug, thiserror::Error)]
67pub enum FileValidateError {
68 #[error("{msg}")]
72 SizeExceeded {
73 actual: u64,
75 max: u64,
77 msg: String,
79 },
80
81 #[error("{msg}")]
85 ExtNotAllowed {
86 ext: String,
88 allowed: Vec<String>,
90 msg: String,
92 },
93
94 #[error("{msg}")]
98 MimeNotAllowed {
99 mime: String,
101 allowed: Vec<String>,
103 msg: String,
105 },
106
107 #[error(transparent)]
109 Io(#[from] std::io::Error),
110
111 #[error("获取 MIME 失败: {0}")]
113 MimeDetect(String),
114}
115
116#[derive(Debug, Clone, Default)]
137pub struct FileValidateRule {
138 pub file_size: Option<u64>,
140 pub file_ext: Option<Vec<String>>,
142 pub file_mime: Option<Vec<String>>,
144}
145
146impl FileValidateRule {
147 pub fn new() -> Self {
149 Self::default()
150 }
151
152 pub fn with_size(mut self, size: u64) -> Self {
154 self.file_size = Some(size);
155 self
156 }
157
158 pub fn with_ext(mut self, ext: &str) -> Self {
160 self.file_ext = Some(parse_ext_list(ext));
161 self
162 }
163
164 pub fn with_ext_vec(mut self, ext: Vec<String>) -> Self {
166 self.file_ext = Some(ext.into_iter().map(|e| e.to_lowercase()).collect());
167 self
168 }
169
170 pub fn with_mime(mut self, mime: &str) -> Self {
172 self.file_mime = Some(parse_mime_list(mime));
173 self
174 }
175
176 pub fn with_mime_vec(mut self, mime: Vec<String>) -> Self {
178 self.file_mime = Some(mime.into_iter().map(|m| m.to_lowercase()).collect());
179 self
180 }
181
182 pub fn default_image() -> Self {
191 Self::new()
192 .with_size(20 * 1024 * 1024)
193 .with_ext("jpg,jpeg,png,gif,bmp")
194 .with_mime("image/jpeg,image/png,image/gif,image/bmp")
195 }
196}
197
198#[derive(Debug, Clone)]
213pub struct FileValidateMessages {
214 pub file_size: String,
216 pub file_ext: String,
218 pub file_mime: String,
220}
221
222impl Default for FileValidateMessages {
223 fn default() -> Self {
230 Self {
231 file_size: "上传文件大小不符!".to_string(),
232 file_ext: "上传文件后缀不允许".to_string(),
233 file_mime: "上传文件MIME类型不允许!".to_string(),
234 }
235 }
236}
237
238impl FileValidateMessages {
239 pub fn default_image() -> Self {
241 Self {
242 file_size: "最大可上传2M图片".to_string(),
243 file_ext: "只能上传jpg,jpeg,png,gif,bmp格式图片".to_string(),
244 file_mime: "只能上传jpg,jpeg,png,gif,bmp格式图片".to_string(),
245 }
246 }
247}
248
249#[derive(Debug, Clone)]
278pub struct FileValidator {
279 rule: FileValidateRule,
280 messages: FileValidateMessages,
281}
282
283impl Default for FileValidator {
284 fn default() -> Self {
285 Self::new()
286 }
287}
288
289impl FileValidator {
290 pub fn new() -> Self {
292 Self {
293 rule: FileValidateRule::default_image(),
294 messages: FileValidateMessages::default_image(),
295 }
296 }
297
298 pub fn with(rule: FileValidateRule, messages: FileValidateMessages) -> Self {
300 Self { rule, messages }
301 }
302
303 pub fn rule(&self) -> &FileValidateRule {
305 &self.rule
306 }
307
308 pub fn messages(&self) -> &FileValidateMessages {
310 &self.messages
311 }
312
313 pub fn check_ext(file: &UploadedFile, allowed: &[String]) -> bool {
325 let ext = file.extension().to_lowercase();
326 allowed.contains(&ext)
327 }
328
329 pub fn check_mime(file: &File, allowed: &[String]) -> Result<bool, FileValidateError> {
341 let mime = file
342 .get_mime()
343 .map_err(|e| FileValidateError::MimeDetect(e.to_string()))?;
344 Ok(allowed.contains(&mime.to_lowercase()))
345 }
346
347 pub fn check_size(file: &File, max: u64) -> Result<bool, FileValidateError> {
356 let actual = file.path().metadata()?.len();
357 Ok(actual <= max)
358 }
359
360 pub fn validate_image(&self, file: &UploadedFile) -> Result<(), FileValidateError> {
369 if let Some(ref allowed_ext) = self.rule.file_ext {
371 if !Self::check_ext(file, allowed_ext) {
372 return Err(FileValidateError::ExtNotAllowed {
373 ext: file.extension().to_lowercase(),
374 allowed: allowed_ext.clone(),
375 msg: self.messages.file_ext.clone(),
376 });
377 }
378 }
379
380 if let Some(ref allowed_mime) = self.rule.file_mime {
382 if !Self::check_mime(file.as_file(), allowed_mime)? {
383 return Err(FileValidateError::MimeNotAllowed {
384 mime: file.as_file().get_mime().unwrap_or_default().to_lowercase(),
385 allowed: allowed_mime.clone(),
386 msg: self.messages.file_mime.clone(),
387 });
388 }
389 }
390
391 if let Some(max_size) = self.rule.file_size {
393 let actual = file.as_file().path().metadata()?.len();
394 if actual > max_size {
395 return Err(FileValidateError::SizeExceeded {
396 actual,
397 max: max_size,
398 msg: self.messages.file_size.clone(),
399 });
400 }
401 }
402
403 Ok(())
404 }
405}
406
407#[derive(Debug, Clone, Copy, PartialEq, Eq)]
424pub enum FileType {
425 Image,
427 Video,
429 File,
431}
432
433impl FileType {
434 pub fn as_str(self) -> &'static str {
436 match self {
437 FileType::Image => "image",
438 FileType::Video => "video",
439 FileType::File => "file",
440 }
441 }
442}
443
444const IMAGE_EXTS: &[&str] = &[
446 "jpg", "png", "jpeg", "bmp", "gif", "icon", "svg", "tif", "webp", "tiff", "avif", "pjp",
447];
448
449const VIDEO_EXTS: &[&str] = &[
451 "mp4", "m3u8", "mp3", "wmv", "mpg", "webm", "mov", "avi", "m4v", "mpeg", "ogv", "asx", "ogm",
452];
453
454pub fn detect_file_type(ext: &str) -> FileType {
466 let ext_lower = ext.to_lowercase();
467 if IMAGE_EXTS.contains(&ext_lower.as_str()) {
468 FileType::Image
469 } else if VIDEO_EXTS.contains(&ext_lower.as_str()) {
470 FileType::Video
471 } else {
472 FileType::File
473 }
474}
475
476pub fn parse_ext_list(s: &str) -> Vec<String> {
493 s.split(',')
494 .map(|p| p.trim().to_lowercase())
495 .filter(|p| !p.is_empty())
496 .collect()
497}
498
499pub fn parse_mime_list(s: &str) -> Vec<String> {
508 s.split(',')
509 .map(|p| p.trim().to_lowercase())
510 .filter(|p| !p.is_empty())
511 .collect()
512}
513
514#[cfg(test)]
519mod tests {
520 use super::*;
521 use crate::upload::UploadedFile;
522 use std::io::Write;
523
524 fn create_temp_file(content: &[u8], suffix: &str) -> tempfile::NamedTempFile {
528 let mut temp = tempfile::Builder::new()
529 .suffix(suffix)
530 .tempfile()
531 .expect("创建临时文件失败");
532 temp.write_all(content).expect("写入临时文件失败");
533 temp.flush().expect("flush 失败");
534 temp
535 }
536
537 #[test]
542 fn test_rule_new() {
543 let rule = FileValidateRule::new();
544 assert!(rule.file_size.is_none());
545 assert!(rule.file_ext.is_none());
546 assert!(rule.file_mime.is_none());
547 }
548
549 #[test]
550 fn test_rule_with_size() {
551 let rule = FileValidateRule::new().with_size(1024);
552 assert_eq!(rule.file_size, Some(1024));
553 }
554
555 #[test]
556 fn test_rule_with_ext() {
557 let rule = FileValidateRule::new().with_ext("jpg,png,GIF");
558 assert_eq!(
559 rule.file_ext,
560 Some(vec![
561 "jpg".to_string(),
562 "png".to_string(),
563 "gif".to_string(),
564 ])
565 );
566 }
567
568 #[test]
569 fn test_rule_with_mime() {
570 let rule = FileValidateRule::new().with_mime("image/jpeg,image/png");
571 assert_eq!(
572 rule.file_mime,
573 Some(vec!["image/jpeg".to_string(), "image/png".to_string(),])
574 );
575 }
576
577 #[test]
578 fn test_rule_default_image() {
579 let rule = FileValidateRule::default_image();
580 assert_eq!(rule.file_size, Some(20 * 1024 * 1024));
582 assert_eq!(
584 rule.file_ext,
585 Some(vec![
586 "jpg".to_string(),
587 "jpeg".to_string(),
588 "png".to_string(),
589 "gif".to_string(),
590 "bmp".to_string(),
591 ])
592 );
593 assert_eq!(
595 rule.file_mime,
596 Some(vec![
597 "image/jpeg".to_string(),
598 "image/png".to_string(),
599 "image/gif".to_string(),
600 "image/bmp".to_string(),
601 ])
602 );
603 }
604
605 #[test]
606 fn test_rule_with_ext_vec() {
607 let rule = FileValidateRule::new().with_ext_vec(vec!["JPG".to_string(), "PNG".to_string()]);
608 assert_eq!(
609 rule.file_ext,
610 Some(vec!["jpg".to_string(), "png".to_string(),])
611 );
612 }
613
614 #[test]
615 fn test_rule_with_mime_vec() {
616 let rule = FileValidateRule::new()
617 .with_mime_vec(vec!["IMAGE/JPEG".to_string(), "IMAGE/PNG".to_string()]);
618 assert_eq!(
619 rule.file_mime,
620 Some(vec!["image/jpeg".to_string(), "image/png".to_string(),])
621 );
622 }
623
624 #[test]
629 fn test_messages_default() {
630 let msgs = FileValidateMessages::default();
631 assert_eq!(msgs.file_size, "上传文件大小不符!");
633 assert_eq!(msgs.file_ext, "上传文件后缀不允许");
634 assert_eq!(msgs.file_mime, "上传文件MIME类型不允许!");
635 }
636
637 #[test]
638 fn test_messages_default_image() {
639 let msgs = FileValidateMessages::default_image();
640 assert_eq!(msgs.file_size, "最大可上传2M图片");
642 assert_eq!(msgs.file_ext, "只能上传jpg,jpeg,png,gif,bmp格式图片");
643 assert_eq!(msgs.file_mime, "只能上传jpg,jpeg,png,gif,bmp格式图片");
644 }
645
646 #[test]
647 fn test_messages_custom() {
648 let msgs = FileValidateMessages {
649 file_size: "文件太大".to_string(),
650 file_ext: "格式不对".to_string(),
651 file_mime: "MIME不对".to_string(),
652 };
653 assert_eq!(msgs.file_size, "文件太大");
654 assert_eq!(msgs.file_ext, "格式不对");
655 assert_eq!(msgs.file_mime, "MIME不对");
656 }
657
658 #[test]
663 fn test_validator_new() {
664 let v = FileValidator::new();
665 assert_eq!(v.rule().file_size, Some(20 * 1024 * 1024));
666 assert_eq!(v.messages().file_size, "最大可上传2M图片");
667 }
668
669 #[test]
670 fn test_validator_with_custom() {
671 let rule = FileValidateRule::new().with_ext("pdf,doc");
672 let msgs = FileValidateMessages::default();
673 let v = FileValidator::with(rule, msgs);
674 assert_eq!(
675 v.rule().file_ext,
676 Some(vec!["pdf".to_string(), "doc".to_string()])
677 );
678 assert_eq!(v.messages().file_ext, "上传文件后缀不允许");
679 }
680
681 #[test]
686 fn test_check_ext_pass() {
687 let temp = create_temp_file(b"hello", ".jpg");
688 let file = UploadedFile::new(temp.path(), "photo.JPG", None, Some(0), true).unwrap();
689 let allowed = parse_ext_list("jpg,jpeg,png,gif,bmp");
690 assert!(FileValidator::check_ext(&file, &allowed));
692 }
693
694 #[test]
695 fn test_check_ext_fail() {
696 let temp = create_temp_file(b"hello", ".txt");
697 let file = UploadedFile::new(temp.path(), "doc.txt", None, Some(0), true).unwrap();
698 let allowed = parse_ext_list("jpg,jpeg,png,gif,bmp");
699 assert!(!FileValidator::check_ext(&file, &allowed));
700 }
701
702 #[test]
703 fn test_check_ext_case_insensitive() {
704 let temp = create_temp_file(b"hello", ".jpg");
706 let file = UploadedFile::new(temp.path(), "photo.JPEG", None, Some(0), true).unwrap();
707 let allowed = parse_ext_list("jpg,jpeg");
708 assert!(FileValidator::check_ext(&file, &allowed));
709 }
710
711 #[test]
716 fn test_check_size_pass() {
717 let temp = create_temp_file(b"hello", ".txt");
718 let file = File::new(temp.path(), false).unwrap();
719 assert!(FileValidator::check_size(&file, 100).unwrap());
721 }
722
723 #[test]
724 fn test_check_size_equal() {
725 let temp = create_temp_file(b"hello", ".txt");
727 let file = File::new(temp.path(), false).unwrap();
728 assert!(FileValidator::check_size(&file, 5).unwrap());
730 }
731
732 #[test]
733 fn test_check_size_fail() {
734 let temp = create_temp_file(b"hello world", ".txt");
735 let file = File::new(temp.path(), false).unwrap();
736 assert!(!FileValidator::check_size(&file, 5).unwrap());
738 }
739
740 #[test]
745 fn test_validate_image_ext_pass() {
746 let temp = create_temp_file(b"\x89PNG\r\n\x1a\n", ".png");
747 let file = UploadedFile::new(temp.path(), "photo.png", None, Some(0), true).unwrap();
748 let v = FileValidator::new();
749 let result = v.validate_image(&file);
751 match result {
754 Ok(()) => {}
755 Err(FileValidateError::ExtNotAllowed { .. }) => panic!("扩展名应通过"),
756 Err(_) => {}
757 }
758 }
759
760 #[test]
761 fn test_validate_image_ext_fail() {
762 let temp = create_temp_file(b"hello", ".txt");
763 let file = UploadedFile::new(temp.path(), "doc.txt", None, Some(0), true).unwrap();
764 let v = FileValidator::new();
765 let result = v.validate_image(&file);
766 assert!(matches!(
768 result,
769 Err(FileValidateError::ExtNotAllowed { .. })
770 ));
771 }
772
773 #[test]
774 fn test_validate_image_size_fail() {
775 let temp = create_temp_file(b"hello world, this is a long file", ".jpg");
778 let file = UploadedFile::new(temp.path(), "photo.jpg", None, Some(0), true).unwrap();
779 let rule = FileValidateRule::new().with_size(5); let v = FileValidator::with(rule, FileValidateMessages::default());
781 let result = v.validate_image(&file);
782 assert!(matches!(
783 result,
784 Err(FileValidateError::SizeExceeded { .. })
785 ));
786 }
787
788 #[test]
789 fn test_validate_image_all_pass() {
790 let png_header = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01";
792 let temp = create_temp_file(png_header, ".png");
793 let file = UploadedFile::new(temp.path(), "photo.png", None, Some(0), true).unwrap();
794 let rule = FileValidateRule::new()
795 .with_ext("png")
796 .with_mime("image/png")
797 .with_size(1024);
798 let v = FileValidator::with(rule, FileValidateMessages::default());
799 let result = v.validate_image(&file);
800 assert!(result.is_ok(), "校验应通过: {:?}", result);
801 }
802
803 #[test]
804 fn test_validate_image_no_rule_passes() {
805 let temp = create_temp_file(b"hello", ".txt");
807 let file = UploadedFile::new(temp.path(), "doc.txt", None, Some(0), true).unwrap();
808 let v = FileValidator::with(FileValidateRule::new(), FileValidateMessages::default());
809 let result = v.validate_image(&file);
810 assert!(result.is_ok());
811 }
812
813 #[test]
814 fn test_validate_image_error_messages() {
815 let temp = create_temp_file(b"hello", ".txt");
817 let file = UploadedFile::new(temp.path(), "doc.txt", None, Some(0), true).unwrap();
818 let v = FileValidator::new(); let result = v.validate_image(&file);
820 match result {
821 Err(FileValidateError::ExtNotAllowed { msg, .. }) => {
822 assert_eq!(msg, "只能上传jpg,jpeg,png,gif,bmp格式图片");
823 }
824 _ => panic!("应返回 ExtNotAllowed"),
825 }
826 }
827
828 #[test]
833 fn test_detect_file_type_image() {
834 assert_eq!(detect_file_type("jpg"), FileType::Image);
836 assert_eq!(detect_file_type("png"), FileType::Image);
837 assert_eq!(detect_file_type("jpeg"), FileType::Image);
838 assert_eq!(detect_file_type("bmp"), FileType::Image);
839 assert_eq!(detect_file_type("gif"), FileType::Image);
840 assert_eq!(detect_file_type("icon"), FileType::Image);
841 assert_eq!(detect_file_type("svg"), FileType::Image);
842 assert_eq!(detect_file_type("tif"), FileType::Image);
843 assert_eq!(detect_file_type("webp"), FileType::Image);
844 assert_eq!(detect_file_type("tiff"), FileType::Image);
845 assert_eq!(detect_file_type("avif"), FileType::Image);
846 assert_eq!(detect_file_type("pjp"), FileType::Image);
847 }
848
849 #[test]
850 fn test_detect_file_type_video() {
851 assert_eq!(detect_file_type("mp4"), FileType::Video);
853 assert_eq!(detect_file_type("m3u8"), FileType::Video);
854 assert_eq!(detect_file_type("mp3"), FileType::Video);
855 assert_eq!(detect_file_type("wmv"), FileType::Video);
856 assert_eq!(detect_file_type("mpg"), FileType::Video);
857 assert_eq!(detect_file_type("webm"), FileType::Video);
858 assert_eq!(detect_file_type("mov"), FileType::Video);
859 assert_eq!(detect_file_type("avi"), FileType::Video);
860 assert_eq!(detect_file_type("m4v"), FileType::Video);
861 assert_eq!(detect_file_type("mpeg"), FileType::Video);
862 assert_eq!(detect_file_type("ogv"), FileType::Video);
863 assert_eq!(detect_file_type("asx"), FileType::Video);
864 assert_eq!(detect_file_type("ogm"), FileType::Video);
865 }
866
867 #[test]
868 fn test_detect_file_type_file() {
869 assert_eq!(detect_file_type("pdf"), FileType::File);
871 assert_eq!(detect_file_type("doc"), FileType::File);
872 assert_eq!(detect_file_type("xls"), FileType::File);
873 assert_eq!(detect_file_type("zip"), FileType::File);
874 assert_eq!(detect_file_type("exe"), FileType::File);
875 assert_eq!(detect_file_type("php"), FileType::File);
876 }
877
878 #[test]
879 fn test_detect_file_type_case_insensitive() {
880 assert_eq!(detect_file_type("JPG"), FileType::Image);
883 assert_eq!(detect_file_type("MP4"), FileType::Video);
884 assert_eq!(detect_file_type("PDF"), FileType::File);
885 }
886
887 #[test]
888 fn test_file_type_as_str() {
889 assert_eq!(FileType::Image.as_str(), "image");
890 assert_eq!(FileType::Video.as_str(), "video");
891 assert_eq!(FileType::File.as_str(), "file");
892 }
893
894 #[test]
899 fn test_parse_ext_list_basic() {
900 let list = parse_ext_list("jpg,jpeg,png,gif,bmp");
902 assert_eq!(list, vec!["jpg", "jpeg", "png", "gif", "bmp"]);
903 }
904
905 #[test]
906 fn test_parse_ext_list_lowercase() {
907 let list = parse_ext_list("JPG,JPEG,PNG");
909 assert_eq!(list, vec!["jpg", "jpeg", "png"]);
910 }
911
912 #[test]
913 fn test_parse_ext_list_trim() {
914 let list = parse_ext_list("jpg, jpeg , png");
916 assert_eq!(list, vec!["jpg", "jpeg", "png"]);
917 }
918
919 #[test]
920 fn test_parse_ext_list_empty() {
921 let list = parse_ext_list("");
922 assert!(list.is_empty());
923 }
924
925 #[test]
926 fn test_parse_mime_list_basic() {
927 let list = parse_mime_list("image/jpeg,image/png,image/gif,image/bmp");
928 assert_eq!(
929 list,
930 vec!["image/jpeg", "image/png", "image/gif", "image/bmp"]
931 );
932 }
933
934 #[test]
935 fn test_parse_mime_list_lowercase() {
936 let list = parse_mime_list("IMAGE/JPEG,IMAGE/PNG");
937 assert_eq!(list, vec!["image/jpeg", "image/png"]);
938 }
939
940 #[test]
946 fn test_php_behavior_default_image_rule() {
947 let rule = FileValidateRule::default_image();
948 assert_eq!(rule.file_size, Some(20971520));
950 assert_eq!(
952 rule.file_ext,
953 Some(
954 ["jpg", "jpeg", "png", "gif", "bmp"]
955 .iter()
956 .map(|&s| s.to_string())
957 .collect::<Vec<_>>()
958 )
959 );
960 assert_eq!(
962 rule.file_mime,
963 Some(
964 ["image/jpeg", "image/png", "image/gif", "image/bmp"]
965 .iter()
966 .map(|&s| s.to_string())
967 .collect::<Vec<_>>()
968 )
969 );
970 }
971
972 #[test]
974 fn test_php_behavior_default_image_messages() {
975 let msgs = FileValidateMessages::default_image();
976 assert_eq!(msgs.file_size, "最大可上传2M图片");
978 assert_eq!(msgs.file_ext, "只能上传jpg,jpeg,png,gif,bmp格式图片");
980 assert_eq!(msgs.file_mime, "只能上传jpg,jpeg,png,gif,bmp格式图片");
982 }
983
984 #[test]
986 fn test_php_behavior_check_ext_lowercase() {
987 let temp = create_temp_file(b"hello", ".jpg");
988 let file = UploadedFile::new(temp.path(), "PHOTO.JPG", None, Some(0), true).unwrap();
990 let allowed = parse_ext_list("jpg,jpeg,png,gif,bmp");
991 assert!(FileValidator::check_ext(&file, &allowed));
993 }
994
995 #[test]
997 fn test_php_behavior_check_mime_lowercase() {
998 let png_header = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01";
1000 let temp = create_temp_file(png_header, ".png");
1001 let file = File::new(temp.path(), false).unwrap();
1002 let allowed = parse_mime_list("image/png,image/jpeg");
1004 assert!(FileValidator::check_mime(&file, &allowed).unwrap());
1006 }
1007
1008 #[test]
1010 fn test_php_behavior_check_size_leq() {
1011 let temp = create_temp_file(b"hello", ".txt"); let file = File::new(temp.path(), false).unwrap();
1014 assert!(FileValidator::check_size(&file, 5).unwrap());
1016 assert!(FileValidator::check_size(&file, 10).unwrap());
1018 assert!(!FileValidator::check_size(&file, 4).unwrap());
1020 }
1021
1022 #[test]
1024 fn test_php_behavior_file_type_classification() {
1025 let image_count = [
1027 "jpg", "png", "jpeg", "bmp", "gif", "icon", "svg", "tif", "webp", "tiff", "avif", "pjp",
1028 ]
1029 .iter()
1030 .filter(|&&e| detect_file_type(e) == FileType::Image)
1031 .count();
1032 assert_eq!(image_count, 12);
1033
1034 let video_count = [
1036 "mp4", "m3u8", "mp3", "wmv", "mpg", "webm", "mov", "avi", "m4v", "mpeg", "ogv", "asx",
1037 "ogm",
1038 ]
1039 .iter()
1040 .filter(|&&e| detect_file_type(e) == FileType::Video)
1041 .count();
1042 assert_eq!(video_count, 13);
1043
1044 assert_eq!(detect_file_type("pdf"), FileType::File);
1046 assert_eq!(detect_file_type("xyz"), FileType::File);
1047 assert_eq!(detect_file_type(""), FileType::File);
1048 }
1049
1050 #[test]
1053 fn test_php_behavior_validate_image_only() {
1054 let temp = create_temp_file(b"hello", ".txt");
1057 let file = UploadedFile::new(temp.path(), "doc.txt", None, Some(0), true).unwrap();
1058 let v = FileValidator::new();
1059 let result = v.validate_image(&file);
1061 assert!(matches!(
1062 result,
1063 Err(FileValidateError::ExtNotAllowed { .. })
1064 ));
1065 }
1066
1067 #[test]
1069 fn test_validate_order_ext_first() {
1070 let temp = create_temp_file(b"hello", ".txt");
1072 let file = UploadedFile::new(temp.path(), "doc.txt", None, Some(0), true).unwrap();
1073 let rule = FileValidateRule::new()
1074 .with_ext("jpg")
1075 .with_mime("image/jpeg")
1076 .with_size(1); let v = FileValidator::with(rule, FileValidateMessages::default());
1078 let result = v.validate_image(&file);
1079 assert!(matches!(
1081 result,
1082 Err(FileValidateError::ExtNotAllowed { .. })
1083 ));
1084 }
1085
1086 #[test]
1088 fn test_validate_order_mime_before_size() {
1089 let png_header = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01";
1092 let temp = create_temp_file(png_header, ".jpg");
1093 let file = UploadedFile::new(temp.path(), "photo.jpg", None, Some(0), true).unwrap();
1094 let rule = FileValidateRule::new()
1095 .with_ext("jpg")
1096 .with_mime("image/jpeg") .with_size(1); let v = FileValidator::with(rule, FileValidateMessages::default());
1099 let result = v.validate_image(&file);
1100 assert!(matches!(
1102 result,
1103 Err(FileValidateError::MimeNotAllowed { .. })
1104 ));
1105 }
1106}