FileUtils.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. //
  2. // FileUtils.m
  3. // zhuxin
  4. //
  5. // Created by 豆豆 on 14/11/24.
  6. // Copyright (c) 2014年 ding wei. All rights reserved.
  7. //
  8. #import "FileUtils.h"
  9. #import <CommonCrypto/CommonDigest.h>
  10. #import "NSDate+Common.h"
  11. #import "NSDate+Helper.h"
  12. #import "Utils.h"
  13. #define FileHashDefaultChunkSizeForReadingData 1024*8
  14. @interface FileUtils()<UIDocumentInteractionControllerDelegate>
  15. @property(nonatomic,retain)UIDocumentInteractionController *documentInteractionController;
  16. @property (nonatomic , weak)UIViewController *fileShowController;
  17. @end
  18. static FileUtils *fileUtils;
  19. @implementation FileUtils
  20. + (long long) fileSizeAtPath:(NSString*) filePath{
  21. NSFileManager* manager = [NSFileManager defaultManager];
  22. if ([manager fileExistsAtPath:filePath]){
  23. return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
  24. }
  25. return 0;
  26. }
  27. //用户文件保存目录
  28. +(NSString *)userFileDir
  29. {
  30. NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  31. NSString *documentPath=[paths objectAtIndex:0];
  32. documentPath = [documentPath stringByAppendingPathComponent:@"/user_file"];
  33. NSFileManager* manager = [NSFileManager defaultManager];
  34. BOOL isd;
  35. BOOL isEx = [manager fileExistsAtPath:documentPath isDirectory:&isd];
  36. if (!isEx) {
  37. [manager createDirectoryAtPath:documentPath withIntermediateDirectories:NO attributes:Nil error:nil];
  38. }
  39. return documentPath;
  40. }
  41. //返回一个路径
  42. +(NSString *)userFileDirTemp
  43. {
  44. NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  45. NSString *documentPath=[paths objectAtIndex:0];
  46. documentPath = [documentPath stringByAppendingPathComponent:@"/user_file_temp"];
  47. NSFileManager* manager = [NSFileManager defaultManager];
  48. BOOL isd;
  49. BOOL isEx = [manager fileExistsAtPath:documentPath isDirectory:&isd];
  50. if (!isEx) {
  51. [manager createDirectoryAtPath:documentPath withIntermediateDirectories:NO attributes:Nil error:nil];
  52. }
  53. return documentPath;
  54. }
  55. //获取声音文件的路径 并返回它的完整路径
  56. + (NSString *)voiceFilePath:(NSString*)fileName {
  57. //获取Documents目录的路径
  58. // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  59. // NSString *documentsDirectory = [paths objectAtIndex:0];
  60. //拼接 voice 成为一个完整的路径
  61. /*
  62. stringByAppendingPathComponent: 是在 路径<documentsDictionary>后面添加 '/' 连接 <voice>
  63. stringByAppendingString: 是在 documentsDictionary 后面添加后缀的意思
  64. */
  65. // NSString *voiceDirectory = [documentsDirectory stringByAppendingPathComponent:@"voice"];
  66. //fileExissAtPath: 判断路径是否存在
  67. if ( ! [[NSFileManager defaultManager] fileExistsAtPath:VoiceFolderFullRouter]) {
  68. //如果不存在 就创建路径
  69. [[NSFileManager defaultManager] createDirectoryAtPath:VoiceFolderFullRouter withIntermediateDirectories:YES attributes:nil error:NULL];
  70. }
  71. return [VoiceFolderFullRouter stringByAppendingPathComponent:fileName];
  72. }
  73. +(NSString *)getFileNameFromDownloadUrl:(NSString*) url
  74. {
  75. NSString *fileName = [url lastPathComponent];
  76. NSArray *strarray = [fileName componentsSeparatedByString:@"?"];
  77. fileName = strarray[1];
  78. return fileName;
  79. }
  80. //从获取MD5
  81. +(NSString *)getMd5FromDownloadUrl:(NSString*) url{
  82. NSString *md5 = [url lastPathComponent];
  83. NSArray *strarray = [md5 componentsSeparatedByString:@"?"];
  84. md5 = strarray[0];
  85. md5 = [md5 stringByDeletingPathExtension];
  86. return md5;
  87. }
  88. //根据nsdata获取md5值
  89. + (NSString*)getMD5WithData:(NSData *)data
  90. {
  91. const char* original_str = (const char *)[data bytes];
  92. unsigned char digist[CC_MD5_DIGEST_LENGTH]; //CC_MD5_DIGEST_LENGTH = 16
  93. CC_MD5(original_str, strlen(original_str), digist);
  94. NSMutableString* outPutStr = [NSMutableString stringWithCapacity:10];
  95. for(int i =0; i<CC_MD5_DIGEST_LENGTH;i++){
  96. [outPutStr appendFormat:@"%02x",digist[i]];//小写x表示输出的是小写MD5,大写X表示输出的是大写MD5
  97. }
  98. return [outPutStr lowercaseString];
  99. }
  100. + (NSString *)getFileExtWithFileName:(NSString *)fileName
  101. {
  102. NSString *ext = [fileName componentsSeparatedByString:@"."].lastObject;
  103. return ext;
  104. }
  105. +(NSString*)getFileMD5WithPath:(NSString*)path
  106. {
  107. return (__bridge_transfer NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);
  108. }
  109. +(FileModel *)getFileModelWithPath:(NSString*)path
  110. {
  111. // path = [NSString stringWithFormat:@"%@/%@",FileFolderFullRouter,path];
  112. NSFileManager *fileMgr = [NSFileManager defaultManager];
  113. if([fileMgr fileExistsAtPath:[NSString stringWithFormat:@"%@/%@",FileFolderFullRouter,path]])
  114. {
  115. FileModel *fileModel = [FileModel new];
  116. fileModel.birefFileType = BriefFileTypeOther;
  117. fileModel.fileSize = [NSString stringWithFormat:@"%lld",[[fileMgr attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@",FileFolderFullRouter,path] error:nil]fileSize]];
  118. fileModel.fileName = path.lastPathComponent;
  119. fileModel.fileLocalPath = path;
  120. fileModel.fileCreateTime = [[fileMgr attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@",FileFolderFullRouter,path] error:nil]fileCreationDate];
  121. fileModel.md5 = [self getFileMD5WithPath:fileModel.fileFullLocalPath];
  122. return fileModel;
  123. }else return nil;
  124. }
  125. +(FileModel *)getPicFileModelWithPath:(NSString*)path;//从本地文件获取图片文件属性,大小单位byte
  126. {
  127. NSFileManager *fileMgr = [NSFileManager defaultManager];
  128. if([fileMgr fileExistsAtPath:[NSString stringWithFormat:@"%@/%@",PhotosMessageDir,path]])
  129. {
  130. FileModel *fileModel = [FileModel new];
  131. fileModel.birefFileType = BriefFileTypePic;
  132. fileModel.fileSize = [NSString stringWithFormat:@"%lld",[[fileMgr attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@",PhotosMessageDir,path] error:nil]fileSize]];
  133. fileModel.fileLocalPath = path;
  134. fileModel.fileCreateTime = [[fileMgr attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@",PhotosMessageDir,path] error:nil]fileCreationDate];
  135. fileModel.fileName = [NSString stringWithFormat:@"%@",[fileModel.fileCreateTime stringWithFormat:@"yyyy-MM-dd hh:mm:ss"]];
  136. fileModel.md5 = [self getFileMD5WithPath:fileModel.fileFullLocalPath];
  137. return fileModel;
  138. }else return nil;
  139. }
  140. // ****** 这里不懂 ****** //
  141. CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData) {
  142. // Declare needed variables
  143. CFStringRef result = NULL;
  144. CFReadStreamRef readStream = NULL;
  145. // Get the file URL
  146. CFURLRef fileURL =
  147. CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
  148. (CFStringRef)filePath,
  149. kCFURLPOSIXPathStyle,
  150. (Boolean)false);
  151. if (!fileURL) goto done;
  152. // Create and open the read stream
  153. readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
  154. (CFURLRef)fileURL);
  155. if (!readStream) goto done;
  156. bool didSucceed = (bool)CFReadStreamOpen(readStream);
  157. if (!didSucceed) goto done;
  158. // Initialize the hash object
  159. CC_MD5_CTX hashObject;
  160. CC_MD5_Init(&hashObject);
  161. // Make sure chunkSizeForReadingData is valid
  162. if (!chunkSizeForReadingData) {
  163. chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
  164. }
  165. // Feed the data to the hash object
  166. bool hasMoreData = true;
  167. while (hasMoreData) {
  168. uint8_t buffer[chunkSizeForReadingData];
  169. CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer));
  170. if (readBytesCount == -1) break;
  171. if (readBytesCount == 0) {
  172. hasMoreData = false;
  173. continue;
  174. }
  175. CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);
  176. }
  177. // Check if the read operation succeeded
  178. didSucceed = !hasMoreData;
  179. // Compute the hash digest
  180. unsigned char digest[CC_MD5_DIGEST_LENGTH];
  181. CC_MD5_Final(digest, &hashObject);
  182. // Abort if the read operation failed
  183. if (!didSucceed) goto done;
  184. // Compute the string result
  185. char hash[2 * sizeof(digest) + 1];
  186. for (size_t i = 0; i < sizeof(digest); ++i) {
  187. snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
  188. }
  189. result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hash,kCFStringEncodingUTF8);
  190. done:
  191. if (readStream) {
  192. CFReadStreamClose(readStream);
  193. CFRelease(readStream);
  194. }
  195. if (fileURL) {
  196. CFRelease(fileURL);
  197. }
  198. return result;
  199. }
  200. + (FileUtils *)shareFileUtils
  201. {
  202. static dispatch_once_t onceToken;
  203. dispatch_once(&onceToken, ^{
  204. fileUtils = [[FileUtils alloc]init];
  205. });
  206. return fileUtils;
  207. }
  208. //文件预览
  209. - (void)filePreViewWithOrigionPath:(NSString *)path showController:(UIViewController *)viewController
  210. {
  211. self.fileShowController = viewController;
  212. //原始path
  213. if ([[path.lastPathComponent componentsSeparatedByString:@"."].lastObject isEqualToString:@"txt"]||[[path.lastPathComponent componentsSeparatedByString:@"."].lastObject isEqualToString:@"TXT"]) {
  214. //[URLSTR stringByReplacingOccurrencesOfString:@"file://" withString:@""]
  215. [self transformEncodingWithFilePath:path];
  216. }
  217. path = [[NSString stringWithFormat:@"file://%@",path]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  218. self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL URLWithString:path]];
  219. self.documentInteractionController.delegate = self;//设置代理
  220. [Utils showWaitingToView:self.fileShowController.view];
  221. __block BOOL canpreview;
  222. __weak typeof(self.fileShowController.view)weakView = self.fileShowController.view;
  223. __weak typeof(self)weakself = self;
  224. dispatch_async(dispatch_get_main_queue(), ^{
  225. canpreview = [weakself.documentInteractionController presentPreviewAnimated:NO];
  226. [Utils HiddenWaitingToView:weakView];
  227. if (canpreview){
  228. //可预览的格式
  229. weakself.documentInteractionController.name = [path.lastPathComponent stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  230. }
  231. else{
  232. [weakself.documentInteractionController presentOptionsMenuFromBarButtonItem:weakself.fileShowController.navigationItem.rightBarButtonItem animated:YES];
  233. }
  234. });
  235. }
  236. + (void)authClearFiles
  237. {
  238. //
  239. // GeneralSetting *generalSetting = [GeneralSetting returnGeneralSetting];
  240. //
  241. // if (generalSetting.isNeedClearFileOnTime.integerValue) {
  242. //
  243. // NSError *error = nil;
  244. //
  245. // NSArray *fileContents = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:FileFolderFullRouter error:&error];
  246. //
  247. // NSArray *photoContents = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:PhotosMessageDir error:&error];
  248. //
  249. // for (NSString *fileContent in fileContents) {
  250. //
  251. // NSDate *contentDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@",FileFolderFullRouter,fileContent] error:&error]fileCreationDate];
  252. //
  253. // NSTimeInterval expirTime = [[NSDate date] timeIntervalSinceDate:contentDate];
  254. //
  255. // if (expirTime >= generalSetting.clearFileTimeCycle.integerValue * 24 * 3600){
  256. //
  257. // [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@",FileFolderFullRouter,fileContent] error:&error];
  258. //
  259. // }
  260. // }
  261. //
  262. //
  263. // for (NSString *photoContent in photoContents) {
  264. //
  265. // NSDate *contentDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@",PhotosMessageDir,photoContent] error:&error]fileCreationDate];
  266. //
  267. // NSTimeInterval expirTime = [[NSDate date] timeIntervalSinceDate:contentDate];
  268. //
  269. // if (expirTime >= generalSetting.clearFileTimeCycle.integerValue * 24 * 3600){
  270. //
  271. // [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@",PhotosMessageDir,photoContent] error:&error];
  272. //
  273. // }
  274. // }
  275. //
  276. //
  277. // }
  278. }
  279. #pragma MARK --
  280. #pragma MARK -- doucumentControllerDleegate
  281. -(UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller{
  282. return self.fileShowController;
  283. }
  284. - (void)transformEncodingWithFilePath:(NSString *)filePath
  285. { //调用上述转码方法获取正常字符串
  286. NSString *body = [self examineTheFilePathStr:filePath]; //转换为二进制
  287. if (body) {
  288. NSData *data = [body dataUsingEncoding:NSUTF16StringEncoding]; //覆盖原来的文件
  289. [data writeToFile:filePath atomically:YES];
  290. }
  291. //此时在读取该文件,就是正常格式啦
  292. }
  293. - (NSString *)examineTheFilePathStr:(NSString *)str
  294. {
  295. NSStringEncoding *useEncodeing = nil;
  296. //带编码头的如utf-8等,这里会识别出来
  297. NSString *body = [NSString stringWithContentsOfFile:str usedEncoding:useEncodeing error:nil];//识别不到,按GBK编码再解码一次.这里不能先按GB18030解码,否则会出现整个文档无换行bug
  298. if (!body) {
  299. body = [NSString stringWithContentsOfFile:str encoding:0x80000632 error:nil];
  300. }
  301. //还是识别不到,按GB18030编码再解码一次.
  302. if (!body) {
  303. body = [NSString stringWithContentsOfFile:str encoding:0x80000631 error:nil];
  304. }
  305. return body;//有值代表需要转换 为空表示不需要转换
  306. }
  307. @end