合同小程序前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
6.6 KiB

3 months ago
  1. import Base64 from "android.util.Base64";
  2. import MimeTypeMap from "android.webkit.MimeTypeMap";
  3. import ByteArrayOutputStream from 'java.io.ByteArrayOutputStream';
  4. import File from "java.io.File";
  5. import FileInputStream from "java.io.FileInputStream";
  6. import FileOutputStream from "java.io.FileOutputStream";
  7. import InputStream from 'java.io.InputStream';
  8. // import IOException from "java.io.IOException";
  9. import { ProcessFileOptions, NullableString } from '../interface'
  10. type NullByteArray = ByteArray | null
  11. function inputStreamToArray(inputStream : InputStream) : NullByteArray {
  12. try {
  13. let bos : ByteArrayOutputStream = new ByteArrayOutputStream()
  14. let bytes : ByteArray = new ByteArray(1024)
  15. do {
  16. let length = inputStream.read(bytes)
  17. if (length != -1) {
  18. bos.write(bytes, 0, length)
  19. } else {
  20. break
  21. }
  22. } while (true)
  23. bos.close()
  24. return bos.toByteArray()
  25. } catch (e : Throwable) {
  26. return null;
  27. }
  28. }
  29. function getMimeType(filePath : string) : NullableString {
  30. const extension = MimeTypeMap.getFileExtensionFromUrl(filePath);
  31. if (extension == null) return null
  32. return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
  33. }
  34. export function getResourcePath(path : string) : string | null {
  35. let uri = path
  36. if (uri.startsWith("http") || uri.startsWith("<svg") || uri.startsWith("data:image/")) {
  37. return uri
  38. }
  39. if (uri.startsWith("file://")) {
  40. uri = uri.substring("file://".length)
  41. } else if (uri.startsWith("unifile://")) {
  42. uri = UTSAndroid.convert2AbsFullPath(uri)
  43. } else {
  44. uri = UTSAndroid.convert2AbsFullPath(uri)
  45. if (uri.startsWith("/android_asset/")) {
  46. try {
  47. const context = UTSAndroid.getUniActivity()!;
  48. const inputStream = context.getResources()!.getAssets().open(path.replace('/android_asset/', ''))
  49. inputStream.close();
  50. return uri
  51. } catch (e) {
  52. return null
  53. }
  54. }
  55. }
  56. const file = new File(uri)
  57. if (file.exists()) {
  58. return uri
  59. }
  60. return null
  61. }
  62. /**
  63. * 检查路径存在性及类型 (Android 实现)
  64. * @param path 要检查的完整路径(支持内部存储和外部存储路径)
  65. * @return Pair<是否存在, 是否是目录>
  66. */
  67. export function checkExistence(filePath : string):boolean[] {
  68. const path = getResourcePath(filePath)
  69. const file = new File(path)
  70. const exists = file.exists()
  71. if(exists) {
  72. return [true, file.isDirectory]
  73. } else {
  74. return [false, false]
  75. }
  76. }
  77. /**
  78. * 检查路径是否存在
  79. * @param path 要检查的完整路径
  80. */
  81. export function isExists(filePath : string):boolean {
  82. const result = checkExistence(filePath);
  83. return result[0]
  84. }
  85. /**
  86. * 检查路径是否是存在的目录
  87. * @param path 要检查的完整路径
  88. */
  89. export function isDirectory(filePath : string):boolean {
  90. const result = checkExistence(filePath);
  91. return result[0] && result[1]
  92. }
  93. /**
  94. * 检查指定路径是否为存在的文件
  95. * @param path 要检查的完整路径
  96. * @return 当且仅当路径存在且是普通文件时返回 true
  97. */
  98. export function isFile(filePath : string):boolean {
  99. const result = checkExistence(filePath);
  100. return result[0] && !result[1]
  101. }
  102. export function fileToBase64(filePath : string) : NullableString {
  103. try {
  104. const context = UTSAndroid.getUniActivity()!;
  105. let path = filePath;
  106. let imageBytes : NullByteArray = null
  107. if (path.startsWith("file://")) {
  108. path = path.replace("file://", "")
  109. } else {
  110. // if(!path.startsWith("/storage") && !path.startsWith("/android_asset/"))
  111. // path = UTSAndroid.getResourcePath(path)
  112. path = UTSAndroid.convert2AbsFullPath(path)
  113. }
  114. if (path.startsWith("/android_asset/")) {
  115. imageBytes = inputStreamToArray(context.getResources()!.getAssets().open(path.replace('/android_asset/', '')))
  116. } else {
  117. const file = new File(path)
  118. if (file.exists()) {
  119. let fis : FileInputStream = new FileInputStream(file);
  120. imageBytes = inputStreamToArray(fis);
  121. fis.close();
  122. }
  123. }
  124. if (imageBytes == null) return null
  125. return Base64.encodeToString(imageBytes, Base64.DEFAULT)
  126. } catch (e) {
  127. return null
  128. }
  129. }
  130. export function fileToDataURL(filePath : string) : NullableString {
  131. const base64 = fileToBase64(filePath)
  132. const mimeType = getMimeType(filePath);
  133. if (base64 == null || mimeType == null) return null;
  134. return "data:" + mimeType + ";base64," + base64;
  135. }
  136. function getFileExtensionFromDataURL(dataURL : string) : string {
  137. const commaIndex = dataURL.indexOf(",");
  138. const mimeType = dataURL.substring(0, commaIndex).replace("data:", "").replace(";base64", "");
  139. const mimeTypeParts = mimeType.split("/");
  140. return mimeTypeParts[1];
  141. }
  142. function dataURLToBytes(dataURL : string) : ByteArray {
  143. const commaIndex = dataURL.indexOf(",");
  144. const base64 = dataURL.substring(commaIndex + 1);
  145. return Base64.decode(base64, Base64.DEFAULT);
  146. }
  147. export function dataURLToFile(dataURL : string, filename : NullableString = null) : NullableString {
  148. try {
  149. const bytes = dataURLToBytes(dataURL);
  150. const name = filename ?? `${Date.now()}.${getFileExtensionFromDataURL(dataURL)}`;
  151. const cacheDir = UTSAndroid.getAppCachePath()!;
  152. const destFile = new File(cacheDir, name);
  153. const path = new File(cacheDir);
  154. if(!path.exists()){
  155. path.mkdir();
  156. }
  157. const fos = new FileOutputStream(destFile)
  158. fos.write(bytes);
  159. fos.close();
  160. return `${cacheDir}${name}`
  161. } catch (e) {
  162. console.error('dataURLToFile::', e)
  163. return null
  164. }
  165. }
  166. // function requestSystemPermission(fun:()=> void) {
  167. // let permissionNeed = ["android.permission.WRITE_EXTERNAL_STORAGE"]
  168. // UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionNeed, function (allRight : boolean, _ : string[]) {
  169. // if (allRight) {
  170. // // 权限请求成功
  171. // console.log(`allRight`, allRight)
  172. // fun()
  173. // } else {
  174. // //用户拒绝了部分权限
  175. // }
  176. // }, function (_ : boolean, _ : string[]) {
  177. // //用户拒绝了部分权限
  178. // })
  179. // }
  180. export function processFile(options : ProcessFileOptions) {
  181. if (options.type == 'toBase64') {
  182. const res = fileToBase64(options.path)
  183. const err = 'fileToBase64: 解析失败'
  184. if (res != null) {
  185. options.success?.(res)
  186. options.complete?.(res)
  187. } else {
  188. options.complete?.(err)
  189. options.fail?.(err)
  190. }
  191. } else if (options.type == 'toDataURL') {
  192. const res = fileToDataURL(options.path)
  193. const err = 'fileToDataURL: 解析失败'
  194. if (res != null) {
  195. options.success?.(res)
  196. options.complete?.(res)
  197. } else {
  198. options.complete?.(err)
  199. options.fail?.(err)
  200. }
  201. } else if (options.type == 'toFile') {
  202. const res = dataURLToFile(options.path, options.filename)
  203. const err = 'dataURLToFile: 解析失败'
  204. if (res != null) {
  205. options.success?.(res)
  206. options.complete?.(res)
  207. } else {
  208. options.complete?.(err)
  209. options.fail?.(err)
  210. }
  211. }
  212. }