根据文件管理系统,逐文件地、初步修改了OA系统,并成功登录

This commit is contained in:
my-style
2020-04-07 15:50:38 +08:00
parent 381c8947be
commit d12df2a7b5
47 changed files with 3888 additions and 1642 deletions
Binary file not shown.
+9 -2
View File
@@ -1,5 +1,12 @@
#\u4FEE\u6539\u914D\u7F6E\u6587\u4EF6
#Mon Mar 16 11:20:10 CST 2020
ServerIPAddress=121.15.171.88
#Tue Apr 07 15:45:02 CST 2020
KeyName=/testKey_v3
loginUserName=466D1203678EFB16BE85C8A02E1486B6
ndnBlockChainIPAddress=116.77.74.139
ServerIPAddress=116.77.74.139
ThreadNumberForFileTransfer=5
ndnBlockChainPortAddress=9001
DataPackagePrefix=/ndn/edu/pkusz/OA
LoginStatus=true
loginPassWord=A1B9652D9ED940B8FC63453C50CB3337
ServerPortAddress=6363
@@ -0,0 +1,25 @@
MIIEogIBAAKCAQEA1SfrgYkPWsFCq68QPY/LlaofFZHPsGf3v9xbcSzdOwRlFh1o
c4VOZ6NUqmX4cJtDzsuxcivXyj529VgywrhijreFWlFV8o+94pSGRf3ncQqXXRGM
JdN+Jyk65atPXYZaCb9Qcy0EPcvGy478ysN0vZN9ZLuYMcy4itVpjWCjrKQIhRpI
bPVQ2JO9VYB8ow1emIFMbPlBR2SXeA/Q9hPpl3loqItHzIlcT0QhFzH01QINEy1m
f2cjDaWvHYRobFPTAcv07a956EGXfvodne3BVc6Bcw7tOPJRgQGZPw/iI0vzcITc
XBCJTTnOKbR+5BLmNxdlwVfI1BXTE95nmE/60QIDAQABAoIBABwMlMEG+C5JICzX
bJutQG0BZfXAqkPcao2kwaOy86nAekzesdAByr94jrudj4PB6rpbs44ClvLWJXFD
mepluRJus+2epmC06ZfXU5QCRWJqsmBc3sRbgE5G7qkqUddMxqxhsIR3eAdpuU8w
EbPc5I/NyMJorS5gcihSzQD9powhDA392rFrh5yoZeoRAondJnv/a4TqcWpL86Zr
bArIR1s/Fmx5uNdi2zkXvXKbDEoWGngwGKs3TKVztsIq8z3LaIoTvZshVtRtAi7X
4tyPaVMuVF2nXU2i1Fi3pa2DowblxeA5VgYT8OgcZom3fXQpnoTDChBYL3x0ftE8
caHkF8ECgYEA/aKcY+XNlbu6sCuya1Qz6O9ot5078Z23UCWhGKAeNYVXjW2Ez7d4
8rDzvF/XxM5jSM920FbdQWsZl/b9yzh31dBYqgoPbCKxyF/NE6Cm66OfaqIiTLBm
vbr1Q9me1TjFrWvk1yk89nPj7Y9ewFWLO0hKlMb4BGUo9dhF40+7TnsCgYEA1ySw
7gxutLH7pYzdXe1+QhgPVYOR5whFUyAdbg8QPMC5USaZEmjInfvKvMAfzRVF0Kn9
VEdpWeUHsNxh4c+vJ8ayO7liugI96738iwt1NJwb3fDfemN+sdPw1XsDUfJWZiML
pjmnq6nrhyFHwgKvAl9RXP0oM+jewYPt7FkIwCMCgYBobFiC8Ivxx7aW7YaplaNB
lb/BSOTzFwHv524p21JUqq9fNOXnNxx+nsfamIMXLfnGclPydrDlTBjfbfsTfg4o
Y3z9lOLAnJAhdP/TwuK2RUlO962zcTT7jEuKQcCY/KS2P6OZygqlVRVUKyDRguat
45eBJWHbPWLdxMsRSTROnQKBgEzphAsGDMmyWzk626SJk7qDKXAzwgQq88Wc1IiV
AAQIDfgR6WUoapf3/Olvca76bOQE8Vig0uvdMdurXZ7BhWed4/fv9Xhz9rkBSXhX
10XAjUHRq8LwMMnX7+ARwwUXsoV+/9okAGohK986KZIVLYWWl9q7chTkqkXaKUN2
LOerAoGAMaeH8w6iQsdBJjmP1Wfk2ZT/Wk47a1RgTqCCahIz5EDGL2/YlTRlIACy
KaWOp9cjHb+sWz4/Mor5unOvTIq3Csa82qGu8sle2PCf8lDfSw+OpaB6jFO6oA56
OGJ2dzdky9OAAO0ldbO8aX23nqoqqcgCIWedboB/lVYAZlfkSTU=
@@ -0,0 +1,25 @@
MIIEowIBAAKCAQEAhZm4MZ8r2h/uBzVLT1DLZCj5J9eF/htay0jhhDU9s4swPsvd
zB1eBBG7IQCyD6BupM0M1jGuRJ64p5Dk17jy/VAuCH5MkCIxXo3C1wAWNKv708gO
CU3LduFg3vjpMP9ceisDfDcCr8ZJ1Mma5JV+7QMsHdTiU41CGUl7bNSn1e0Zq3rY
QGe/HxsSTXGcigl638xGQ9sKdNFrWpQHeHQEoPHylwh4bHKTuN8vGYKQbCpyI3IX
s69Qm3INzgNpCwda1pZLdRKaBDTO91kOZJ9Ln43k2Ic68icaoL8ZDHUD3C6M5b2l
MxSPg2989VV768YNPpiKJskRfY7LlKPy4f5iNQIDAQABAoIBAHDsZ1X59fTefDC3
iTo3TlMQlthoQSdxM6MTrRo0bjyt70+EvapjQC4sVoEkt1yh/CNr9eeuAmCZz/ZC
cEsuVqRp+x7OsiQ54oTLSd60ghBvNeHh/Is8qDeJdHnC5ke18BKK/N0nGiw8a/dh
mHyRJ8FppwZoBA0fHrmE9MAeVuZnxNfns5VWVha4Z1WopSyGT5Ux+G6vMxFlLgen
b9ANMw9v2kHv5+BNvZ81ro2A8vJhL69ig3mJFefkxHoIWhdwl+CtUC3dR2FRb/9w
fSjXi/D6jkHMeOrZjfBcpDikcZ5oVfmOL4HO6PMWnxx6XgG9fQS2HFcF9C5SqnAj
43KGmEECgYEA+phd35ylwRuzBFH0BJNxk7LnYVWSm2FdpGVc06khnOIvG6i+RXuW
PmqFqGxmm3sKpXzMU0gc9Z8o0hg8nIkFCwr2+ZZIdfP70JsEledvxc/J8/CNL5zJ
Fj0NbkuzSjofZ2FBvmyNorLU+OfNyu5MzdUi9iTrJ1yur90+BBNOdF0CgYEAiHth
KuXMa71oajLDWuGDQ2AXrSWhiVBTH+9p39J6cLUzIfmHRtu5Vwxuxsw91HJw0nsH
izAliqWAZvtFGirfjWlrpe3GWtMdOyy8c0UWXCbI6HKBcJxebe8qlsEyg8e0o3Yj
Z73MwsAifwKprzcKZPSiIhogx/5BxjTxU5u4x7kCgYAq5ANFL5mLKMOGHMTIN7g7
0GYb2bqjD5IofhTaQVt4b5oigMo4OEPp4O+JeSxCtleHJYoPQwt52sjw1KcjH6yW
TEUjSN6UGbNi6/Vn9tnBoKPvNZ/ko1Ajl0WCOECylqojVpkbD5daXoNnKr2lWw4Y
OL+oI3+AGDPp89MWfXtzHQKBgE/LuyLmml8/rYWxylAfW6yPySf9wXVUFlWsl706
BUZSWuP5TWNbYgCID1iB34CPrHETZ3S0oK5wVyNes6c5+9xlD4BDBd7iYcvQOxo2
AX29W2e0UwOxGPCzjbX4nP05TN7pWof0C3yt8z1JJEaCKryd3xGLLzFe8bveBl64
xA9ZAoGBAImSFu8nFLtQNCTJza4js2t3P4q9Tg5VIbzeEjdtos/dLqGhGOq1wPMt
WPBFh6r29gMuqDeUgZnZo/XioENspBHV99fakO2nkrwcKinAvmIgriXU82pDNp8j
UemLtcHGaAFfinfmGw4Z5H5aApVzDxEAL1TLKyHcJFXhPu5I7RV4
@@ -0,0 +1,25 @@
MIIEogIBAAKCAQEAnfq8CLJMv7IYQNOUehxTbi3Wtgv5jxbYo7jtw+HLH85jujkX
BL89G4zpGv0+q7ZKkrxYauSUkvuxyQ7Aeg0xao7TIxQgZPMyY4VPJpLSE+xJaach
xqcTJt2snPy6pw/gz8gVj74G70+j1xK2ZkdsZw/iUzPa+jJlK3rI7+l6LsUUVBHa
jEB136njugNC0s8+nBi06h4u6BhBFYYAx4AuZeBar3EcRnHu8u3L5LCzbS9v87Go
05JmlhtGKzDLgFRTGVc49Kvu4YvVTZ/YnNtQeOjP3Uc3WRAHd0ApDfZMZLvRsbxz
4h/h5/58tSW4Z4m3fOn00nD0pitSBuMjsq8wFwIDAQABAoIBAD21s72x6Ej5SIAK
JfWNGwnu3fA+vT0nr3hExJu/l5jVBh+4LUWtbjFU2bmxMsnga0DmUaNvppnDt67S
FF2YybTWFaOeOQk19njpmgF3WJhvtD2RC6CNou2LqeGo10Bq82Y2wjVkBVF1yoo4
xQcu3yljCwV1PBR/mwVg8RzGFvQtaO/CHB6x0RxsOk9mFyOn2US8t4vj6oGVAKj3
7agk3UxGWAiRWPl/x44U7xnXE+6KavbOSguMWzI8LGAwYivNlOg8VhW1NYpuqAZU
LxnwMTC0xHrxQqYtCVRQNl91i+Krkh+0MCH1TkAo+IxJJEmtsGJCB4GrHa+0pcWP
xgr4IAECgYEA6RbOvg6q86H6sVUjWL00ypm9GwBOlDFZNLMWQ8p5NMrpkiHbp43r
IlvSP8IpptImhOhJJs4i84bFt5pkQdqO1FLyLhM3FEaK5LKqlIKNDKfVdW3n0K2d
qoRz38J9UYgtp7ctXttV2oqVUr+F4sylnqGhbRKM+v7zRIWSKJkQ0nsCgYEArYHz
oewqJpQcaNZ4fS/ae+IjUYHbOGs7L5rUocmkXFBeGa8XCl9RqyvxVeg5yqEhn4Mn
3AC7ONWAIXtkMa+IsCgka1cagF57ULcn7oWDRgw3TShvbNXZkWo4+rz0EQT19L75
zcPa06FWrURT1CMH/xjb899iYbR5wgsFWEXMBBUCgYAdbzfkYE3OPmI+CpZQGnSU
MR3kTwGdTS4KraLeJK9xrz4Xqhbm7dEHobjHPGmuG1Op7Ptv3xAi2J4XNXP7rPHk
diUHFH4cHVxkzPsljebp9jfKgHqJq6MBaYCIfTL+HMhHKaadF+2bj2yT6oOpxFYV
1itgbrtG5vMpcASpA8tQCQKBgE5RUDWQsl4DkOdJl816Ija1Fpgd82P+ExMj4kK9
D/GTXUZeoBnQeL648RCD6EIshU7JFt7ZfajjxhhW6Bz9TMem9vl0scOr4iHG6sFh
hqXBsdykGdeYl8Jpnhqf29Mq2BKHeZ6Ff2rzcnp3Uxd4UI23HOFxvai4nBUYgGsd
5j8ZAoGAHRYhOF+zDbK3nGQsuZjsDb3LrngdNjiEPA+hYeh3k2BKwirSKoVUQa62
k0Tb/PRBiPiyQk7uYGwyR9WA8Yr2BA3y+/9m5rNenwJAL/o39DjogV9K/pxSmPH+
FOz29FNtO0WO5IpNaVroKCn+SHSEahFdhdyR6I9J+chFHnsDQDo=
@@ -0,0 +1,25 @@
MIIEpQIBAAKCAQEAs9dajy8yS3WCi15hnHumAP6SELbbusHDqx957OwA4V5YSiXJ
ocgT4k+SPg9y+FgM90XNtiYZbqqi0tXtrIXsNN3VZx4UDQAAoR8Xe2RCuINA9o38
b3roK+3eJnlv0Z6msY7jBawib8ngdyNJMobVPNM2qNT9Z3CE7aNjDvKf/Y4/DeK2
X9ljvK2+XPjMwZ+otlIcS+q027cGlJO4RkHLukGuJbpltkhcGLL+wVvs7lx/Per0
Z/6pTum6LPVar2H+qse4XWpVgIVeMEg1uGmdplqqRV0YR1yzhfuQ0tqOYjHvaPwX
e68zOIyDcqkapvsogztm06E0682uzId9vup66QIDAQABAoIBAFgmN4o1TQa1m34q
jdfAt7aHERtGNd+NeBYZgI7Dgw70SnxVl0ZIJo7oB7uJoQXfSsOtIE6m0BJxawvC
thO5NPUYwrAfix5wIN7YuY7OrvF3zFDNea0+5iwaFKhxH4D0raocamRuYha/MdnT
nt44Pq7orEMG2wpnmZBNZJGAFTGXQiuYCr9UVGnlChn3nNORJrYA6yogjSwJVhVo
4S9g0JNI4pq9bgZk7xQ3J51LbJRT7KEnGHNY9E8+3Ya0uQpD9qGHTeueBnEjjh04
MU7bPfRmfr6E5stQUgt9fK4MmFLGm/DJhI5RGMDIck+8kcWDnP+zzghicscUavmn
XwY9Aq0CgYEA9oAtyUqTCFZGbcHIUu/I4j+vcAoOtIkW5UxNuQJn5jmYuQYJu47o
D9n+AZQVfKrSRgSQw5EqYLx/dkzv1gxmJaM1urfVQG7b/XFtk0CFPhZAFrAT6m5M
RQuqhZ49+F0CYYA4kCeOjDQ3/QUO7ofHOKhKUBBkZn/PQFyJ3EdhLpMCgYEAusWN
69pVMKiT3Rkfo2Lv+uqj+HXCFyiE8ASIulX/VkKnlnFWA9Wiesr3S6PBZBSk58Ky
1lPZdVWTV1DXh2bxSggCVNccxriIQVUCqyWGN3rWhFZvLK7DCcU5cfNGzwnCvisn
JqVENg9fxvBPDI33T1NkcI1QHWTiNiAWTGm5ohMCgYEAocCYyvbJpvXeP1Wi23GH
k5eQyud+oM84m/zHH7lJbpSq9/bTWiU7eHNmr6h5tRXu541FZV+TvGjVB08TLpVy
Tg5cSospP5+/cf8FlVQIWyaEpZ6jYvk/ySsPmaCuL5Tw5AQcmdOrQatedgTkuHeW
rkIYiZNIHs6NtEFFIawhREsCgYEAqk4fhhN1IMRm5/HTvpkluEeispk2HQXOikmo
HzjxdkebJvw7cY2o9Y0DiA5O9qI4aDhJ+FNG883PZ4wIq6e7l0TMU24/CBkV7XTF
1SeHRimVV+C0ySqmH8+d/QDW7Uy6LcuNjJigJSdJr05K1mjRPJ0O9e51QghOmQoT
KyQwp88CgYEAtA/he1Lf81965giwWg6k1Ul2+o4d96eq+aGDesW9awmKQIMVnXPw
9++6uYLNTOazRELEt0+jeuf8T/nqtmjahURhG+rbxj0fvafd0faV07ygIHbpK575
pEMIV3UUZjKUVPqnhSOc7B71k1163prIjIYvjSe2pCq9KxEAORd9Je4=
@@ -0,0 +1,25 @@
MIIEogIBAAKCAQEA1XSNRuSN3o/wayYGHV4FnBL8iofwlRjUJsJEQuGTi5eIVT7j
qL3IalgGJJ5lAFpaLod83NTXG+4lqFnUfQPB7qd0MQyi9xWt3IdzL83t6V7egLx2
DpSd8Y5ZgKasD05LA6/kcmAMv04Vvj/ndwvLmHUTr3j8xNMJMFIWdpB19Zuma7Zr
6UwXh+ylS3bvJPDOcDsQgu2f/Boa7cMhALs76AdM7szrnbnHZbv+dtuxOD609Wjy
albxSLqjpqV3w2Af0/Z5PIa8turNREGqxqI7R7vm/VIUrjU6bpzn2E2/lc3l0sPr
XVydRPc1HJi0k+1ivRsWpevpGE5h5Y7rdtckuQIDAQABAoIBAAaHw0647VIyyyMs
DaHWX4uP1SQT1ptpIAxzgw0cw5vQrf4Vp3dhHwGJ4d467lIdcYbc5EgJRu920LYe
0W5lsAgyHU7m2RGAG0qU5kQ/I5kxKtN7cI0vpMlgFoLmFnt9ZLQfLHkHUTyFEgs4
/0bYGIl4g3qp0+ndnvlYeZF1B/bUlus1VKVjW7tBlXDmst6kcfgi767AAHJjaaaz
Ho9stJR+UT0MIHCz5f+OUrQOfynO1F6K6zVlQBaIgSfmSIhSkzQ10qjhTXka7miF
UEJs580sPg13+EMjSDIWVRe81s9hc9uoeozY+sdnk6AAjhyktU3BijxPdAGZuJyo
1hFEXJECgYEA7ypNV7kMEU8bVNjsFNdpxVoWc6/RgXAYXmJ5kMKC1fXanUxPYGxN
0UWeEhLw3SuL//iAMe9magGeykGsZFr1qcz4eveL0jl5mu8jhv/nZcENemrAHd2P
zBWBe10pvBfT2Wn1dv7Wit3mVz5QpEvdDZNOFTgAYLN5kwf6XGDKdi0CgYEA5Hr2
cKpP+Bk9f6CeCLwvwFyih2oRn9Z2boRLUVrJcWlxB49rWc1nh+EAZWIarjeZh/8r
sDmCJoX60c9GZSyFFEBRQfprW5Ao3RyXNY6oKenBjCWHJUbv041C2qkdTeblls0e
3etqaa/tHL2zLFiOvlAf/8nj1N4psE0duRR2bD0CgYAMf7h1Ci2wReMWxxNnb26O
qsublierzRDo9dqGjzPJPMUFDXTkhCR4+FtvdF/0Hw98/B6u/WTry1PiHBaHVB2c
lyKxQnijLu/FAhRoPL16GuG6cRPDO84FC2at7Mt+kfw3U4tJgb3ymfAsxQvv2ise
R4GAKGIUq6yB25vg8goCrQKBgCdbSwIjRD0vU9mdODu29t7C1jhPPBP1ZFcrMLIl
2ldP22l6+fnxGOleB6xvFrt11luHx+XGMjYilA76Dl01KwNPBPBBi6atEWztFNrj
5PG7U1ypxjrUmlEtnxt9UA/wOxIb6To+6AimhkiSIL/9zTDZKnnsM/OiBTpaPkl4
TeHdAoGAO1Tfl5KcEP/zMSg2hDtmrb90z2fVA4ewoFOo5Y64F99GIepS83MYiwRK
tmmqHqG+DUYOs8sLexfKtZyRyguWxFwW69/aTNomZoeCzP9F/nHg+ns8jZsGwSZY
TpER91D1iiTLhl1Wnz7EPGKQVn1a/OdWkxsiFlFpMMxFAQye6A4=
@@ -0,0 +1,25 @@
MIIEpAIBAAKCAQEAg3GRtC0iPdgugSnyNkp29LDaYNzVjXY46pE+OFSAbFm3X++K
LIinlxqB1cc5nlk82ckzodUzUvGpTbSNib7PKq1625A+k0Ue3WD7aKB+yDoIr66b
ZMqCOx8bpMEOFoHIb/Ua/zDFezZUheX6nVZnTDl3vFf4erx8jZYeC47miJKkjH1l
eiX+U5M9IV4vkU/iIoTyLFOBuqDy95OD7dkFIdOqoSY0MvjuPMT9+bTfBgvVXaYW
kEoLpcdxV6Yq2FhMiCINaYm+dVmg14PYVXLMAsUFzotSZ9jB3JQOcmKZYhyLEke8
6P90KOrDaT7qwzY+h2vovpIf77EXfNve2ezP9QIDAQABAoIBAE9CyYireq1uUcSj
ZaIlTwwIJPcp00CFXJbd1HYlRnePtgsMp/ZoxR5R5p7hjrYUu6PcNt1McbF/dgcc
bAj23XevupjxpzopAQ6fb5rMxQa6MAi4Mo4Zq2Q5QvMbUwJxaktQsuHVKBA/V8KS
Rohf1NRbBv+00Go6hKTgM+fmWM9bM7t2lpuv2dD8Tt5TwqfWINAjfrHUIVBf2HUG
FOpcaOufmdYiVpTkdrx+lfc8uZBBSM7GYDS6WdtotamWsaL9XhBlVzUFgvd6LKOu
A8iju6YRnDBrBy/MrdShAZGv+AruNXW/psxdUNfSPY9jAzTtS3f2/v6liXCY7xNO
anSnlbUCgYEA4zYDutw2WSAtJDcUtpxIxahwX52vRbnSHToYtvJfkxcFeuJ4jj3M
5WBivV7CSvrKGVlL88O9X7QrmouUhNPoQ4cqHOPWnQecKxAiksfdMNl+bn8PV2bP
W5J35rHFtYfzrO/mHz6Et6De9ASGNAUlvFTZORkqu+EKs4HGzgLC9gcCgYEAlBks
P6iaLDUqnkPaUYC87BKCfztFq0vwBAuFmzJiqti/URaaB1ABOX9ICIii9bLKBBpH
UVk4SxMqxFOkfO4aERBWg08eaT4iEvJOBDF9w/x5ElapEA7uw81rAmpwvQszwSiw
p9e1FocoepSsd34eL/V/EkFFhhqrpxjCxan+KyMCgYEA0Xz22W26alhhZpemcGwO
KLgRzAbuGIKouKvdJ6i2+D5sng17C+LtLLu+rk1VJJ6wgci0X6+kxj2vSlHRgNqE
tuZDrNlhAe2HTqkUx3KhfS27BZP/CB3Rp+OWy0wzNxl/UX7rFPmmkkwv5JrbRdFN
JqSwl5WdshZesH1CWKVxLjcCgYEAkDRqt5mudXlXhD/BpzbZvmzPkJ/gWMlabjXh
5JqNJJpkv8poNNKcPqZHN7gEJYXv20rTQszDWabSL9TaB6O40gC8nKM/k26isxwp
B0BBm8KNCWREvpQrvZCZsAKAwDLWNDEwwl3xwHve2G1H+hpdvoknMFlKHyh9F/mu
PdYm3U0CgYBHKh+FWZ2K/MPY/+69+7BgpdvTYoyV/nO4lTDVoLpMsrk6/PwAwwHT
YyXx36E1xGjFvBN46H3UTXd06mI4a8aX3obRDVvzrHAEd1uWAr4ufYvpib2BFMuu
iIfBlsG7qPSdL5af0w8jKiLW6QxegqYVPrtbCCY4JpbcgEXjtL6z0g==
@@ -0,0 +1,25 @@
MIIEowIBAAKCAQEAiA3stSNU6Xkr26SYt/AANIdq1zXCsaErIDM5LIIQ+CG+NK37
bikKdrxouYhJ00lPTP7GyIwRpbORf4Xy9kNad+Xfs0KhWrebyn8ZWsPFVrDX7aVa
Pb68GY2EuQBwGp2dkZjFGUVQKvK6dhwMl3pvtfucjIjg2qAktNw1SFcAy5kjA6JN
pMqh9MbrV9hF7otMvnfXge2VpIglpS8zmT3fbPjXc+V9PhaY9MIBVnMLA+Q1BvXl
X/127NjgSrMLqW+eBYltZzNt8PD142oL4CMR71nR5sJxXrYHmABQtnRYr+ek0is+
6EpAdj92hQ7CXAeeoXacEScODV6NQG7dRMtn4wIDAQABAoIBAEOaR6epqqNn5fb5
Tjj3M+Ll9pyAxgDlCDyztxD6f9wLSCt815XhJqXg8Fhf8+7cWl7zqWo0zv/6va0T
ranXxbgVrJWx4eLloK95f+utovx0WpZmtvQ/Nc+sleom4Y0YDBcwRZ9M5Yyxlxzg
yxDpcWCHaT4bNT7sm9CSKpeLQ4XmEntrOASb3v1G/6bzl5d1M2UXiy85uP2RqSez
uvcugYEGIJTAF2FXH4iISiA0uEvnCu0k4H5CVoe4eu44Ykc86KwHASqwb1Yl/5LF
DOUA4fiy5Grq99gnoOWrPqOfQAZVy16i04+q9qp5BAD9yBsgaLgsgzzhsFm1UAzx
pETc9SECgYEA1Q+ftMsFzLdFa9tzlFzOG4OQu/hFYf2SVweXkpwZk3TMyu9zBTbX
zl9es2ygWYJXwCRl4a6iFOj7j3ucq16Od94MsHl1AtO1XdP2Wx3ppZd5F8a7lyPk
krQaGgealz6y/IqWev5FuzqQuiTOClf+L2OAQkoWgUdpBTxH8aJiIK0CgYEAo3lT
qy9VbHxBh62Mi//C9LXdMzHSZnlf2i1K4VXew8gQHMidxMay6ef/UT4jYRgly5xo
mZoAf5bhmlbgKONVwCsTGi77L+m20QCq4WOfGG770xQtMdAohYvZmfdZhcbxqhmf
IAfXAAR/bAQqYjl9mK7Xyj+GrpUMQLX++YuSbM8CgYBYcYzlWuXEbku2EznuW3v/
deTt8oiyvbUyxWcJKB2B1ZlxoGaJwpNhCrvgFXaW0YGltDZKsdh8f551mGWXyb+w
SI/R7glBrCp8kZGRj2A/KhrNYOTcP70RnQu8xG1K3W8lYE5JLiY6K3yKmN6i8pYE
i/RhECo5bjBNSRHAX50GXQKBgQCiZr7zOoPf0ZV8R7JvxreUSjQlTuKaAQxzgDl6
oMc8sr0nCzqJKWjGrT7dJCEbrVSm8YyMxAyotGkN3i61EBu5XFGO2ouabtG60rHw
VfrQ2Dj+2nWHnicTfPrBVZSvLRQaC3gk5wT1tIIt+fltOXYHv/MKro+LUvEoPGXA
3aKqywKBgGjnOX39Un3MB/15i9qV1Mvh6QJgv5ldlRnYtPKpPU7HCGCieLcS9SgG
6O0bZ1bbbIn5boYg21wq1O0HrSFgDi5DW0JdsBysKDqUAyp7346GCez7z98wYHR0
dInzfUjMgdeQ7JlC5cZi/+ETotKjvZWu1QDaIj2S3UAd9R4MHPP5
@@ -0,0 +1,25 @@
MIIEpAIBAAKCAQEAlP1sWRkjTq25xwcrISI1YHR/CjdTacF1MfBZdDNPQ1krFybr
qtzbUeqjUzwHVMhH6TP6x3H6+k9RCAkcuGbafhsKvKdteN9Yi4doadzQE5HUYsQE
fbGSuC2afN4txIqt40QJKhDnqyi9abr3pRn+sGin14AWBUiMi9n/xd9RcOly6AkG
D/Rr3eEmaBKc/GbvKEpurcCuQURsNu0x0LiBm/sGeBKaPXOU3zqfWiDXS9fjenyi
iMLDZZBD45FQxIa2aFWtNbpPFLCjWJCwlIwtC4kKutZR8k0ZN7rXNavpajEXg33H
0hhgQwWNgMPK04lIyAU6MCiUN6cdL59liuQNbQIDAQABAoIBAAUnWwcd+n2vPrzm
v5Qu1b/XZ8mXrlf7LC2lDcMaP0SqIfZ0DzTi3OdRgYLQkcRaBTrI5ITfqXndIoVv
o0GxtR8lmlJ6TCwhNbPl5DO9QqlaowkjlLAwY03hrfVhzh19WpSA9vwwh4MBLsQo
hoZ8hrXdeOjYcmqOXuY7jUBwACYyr5ZSzp8Q+QXuP1QLiyw6TpotrbB6wkx5JS0U
X2CJWxfllMAYr/mDXSXW4uysLqvYCR/VAu/B2s0kue9WjcsGyRuzP42A4gKGKa/E
/RC6RVqR/WSEPMRlt30+A9zNt/1lkTWF5Nr/8CILtAbdhq2uGxS1qs+Smt1uTdBb
BYYsTzUCgYEAxwunZuQduW6mAajuLC03qT6SrJntBnHnr4hJV203n4kaiBvOO54W
pXt2zFXZ7h9C1ziwIGrtQdVUTfDw+pkZCM7EAt82IYwUp4MB/7Dnbe3nW3nRCEd9
5Q89r0cSLwp8I49jyRjYIb21eZ4NCQRJSryc0L6McqaCbUmm1LJ9Qz8CgYEAv58h
tnKwLfwhXhRNS3UERJ2wGBuuTXGymWyhUTISmPumt0+R8NZRrlJ7zhkLBaDQkA4Q
Zu2GnyZdQ77aBrfXXD1E9gaEO5pukHNZhavSIg48K2nw7eaa0c40iJ2uTbo1nli0
qK/mywAxd4imjCWpYMLwUHXapFRe7bTeCsgowFMCgYEAlDQkL+M4EqLFbkT3GeON
JzIVCfkOWBcluDgUy8jheqMeIyv48cDzAcIdIWXm/3s9THzD/08+Wx9ZRzNYam7m
Cf3SSoUii/X+Rv+v1E9G8j4KXr0kHDMHFS+08TZM3sPCzMNuPASIoQ7c+bHp6MXN
QJ2RcYf/kTpTsMX/Ny2zQQcCgYEAhvLAwUafwKLRtPnDPaLZMKGExFWqOSwbRWV1
bkM/SbHgRTSqaNvmhkfcnNaSJpKMjwb4kiQxLJ/OCsm7rgOGjZUwnbsVIQyvVNeH
clYBFK7FvSVM4Z4H5j28TYIOoPrEjBGYmTvX45rtO2tnL0fOszBWIbP+GMC6YdmA
jkNMP7UCgYA2fubLdBrpoS1ITDzqCzpffQNoGeRq0DqnpDMIYuSqYGvWING0UkY0
w9PHGiVL3p3PisVGOyfv0Zne2bpF6VOOkbGRdd9P82wr85CgsOwt4WQIFRvIEmlu
lx4p38As1CpEDW1wIQ8KOJu6BQoHTI/EuTQDApOEmnaP4I9eQX4Z8A==
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

+469 -277
View File
@@ -2,14 +2,16 @@ package cn.minoa;
import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import cn.minoa.dataRequestInterface.MinoaDataAPI;
import cn.minoa.dataRequestInterface.OrderInfo;
import cn.minoa.dataRequestInterface.ResponseData;
import cn.minoa.dataRequestInterface.*;
import cn.minoa.model.*;
import cn.minoa.util.FileUtil;
import cn.minoa.util.LoggerUtil;
import cn.minoa.util.StringByteLengthUtil;
import cn.minoa.view.NavigationBarController;
import cn.minoa.view.home.*;
import cn.minoa.view.login.KeepLoginStatus;
import cn.minoa.view.login.LoginOverviewController;
import cn.minoa.view.login.RegisterOverviewController;
import cn.minoa.view.login.SettingOverviewController;
@@ -29,6 +31,7 @@ import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
@@ -36,7 +39,9 @@ import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
@@ -86,19 +91,25 @@ public class MainApp extends Application {
// 判断聊天窗口是否已经被完整加载的锁(保证得到新消息时 在控制器已经被加载出来后才更新气泡)
private boolean chatBoxIniFinished; // 标志ChatBox是否初始化完成
// 服务器数据接口
public MinoaDataAPI minoaDataAPI;
// 唯一标识数据请求
private Long dataReqId;
// 服务器数据接口
public volatile static MinoaDataAPI minoaDataAPI;
// 唯一标识数据请求
private static AtomicLong dataReqId = new AtomicLong(0);
// 服务器数据接口参数信息
public String minoaServerIpString;
public Integer minoaServerPortInteger;
public String globalPrefixString;
// 服务器数据接口参数信息
public String minoaServerIpString;
public Integer minoaServerPortInteger;
public static String NDNBlockChainIPAddress;
public static Integer NDNBlockChainPortAddress;
public String globalPrefixString;
public Integer threadNumberForFileTransfer; //文件传输使用的线程数目
// public String pidDbPathString;
// 密钥导出文件的默认文件名称: username_KeyFileNameString
public static String KeyFileNameString="SecretKeyMIN";
// 保存登录者信息
public Loginer loginer;
public static Loginer loginer;
// 保存联系人列表数据
public ObservableList<Person> contactListData = FXCollections.observableArrayList();
// 保存与所有联系人的消息记录
@@ -110,14 +121,14 @@ public class MainApp extends Application {
// 保存通知列表
public ObservableList<SingleNotice> noticeList = FXCollections.observableArrayList();
// 文件下载默认保存到windows本地的路径
public final String fileLocalPath;
// 文件分片包含的最大字节数
public final Integer sliceSize;
// 文件上传默认上传到服务器的路径[用户根目录]
public final String fileServerBinPath;
// 邮件中的附件文件上传到服务器的路径[/share]
public final String sharedFileServerPath;
// 文件下载默认保存到windows本地的路径
public final String fileLocalPath;
// 文件分片包含的最大字节数
public static final Integer sliceSize = 7000;
// 文件上传默认上传到服务器的路径[用户根目录]
public static final String fileServerBinPath = "/";
// 邮件中的附件文件上传到服务器的路径[/share/]
public final String sharedFileServerPath;
// 用户头像的默认保存位置
public final String userHeadPhotoBinPath;
@@ -125,17 +136,19 @@ public class MainApp extends Application {
// 进度条更新任务[传入子线程]
Task copyWorker;
// 标记是否是手动取消了上传或下载操作【false表示未取消,true表示取消】
public boolean isCancelFileTransferFlag;
public static boolean isCancelFileTransferFlag;
// 上传文件进度条stage
private Stage uploadFileDialogStage;
// 下载文件进度条stage
private Stage downloadFileDialogStage;
// 决定心跳包是否需要判断登录状态是否失效
public boolean isNeedKnowLoginStatus=false;
public MainApp() {
// 加载配置文件
loadSettingProperties();
// 初始化一些数据
dataReqId = (long) 0;
minoaDataAPI = new MinoaDataAPI(this);
messageLogMap = new TreeMap<String, ObservableList<SingleMessage>>();
iniNotReadMessageListWhenLogin = new NotReadMessageList();
@@ -144,12 +157,11 @@ public class MainApp extends Application {
contactListFinished = false;
chatBoxIniFinished = false;
fileLocalPath = "E:\\";
fileServerBinPath = "/";
sharedFileServerPath = "/share/";
System.out.println("客户端根目录:"+getClientPath());
userHeadPhotoBinPath = getClientPath() + "\\resources\\images\\headPhotos\\";
// System.out.println(userHeadPhotoBinPath);
sliceSize = 7000;
// sliceSize = 7000;
isCancelFileTransferFlag=false;
// 初始化记录当前显示的面板的字符串
@@ -178,49 +190,57 @@ public class MainApp extends Application {
System.out.println("en bytelength: "+StringByteLengthUtil.getByteLength("en"));
}
// 加载可修改属性的配置文件
public void loadSettingProperties(){
InputStream inputStream = null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream=new BufferedInputStream(new FileInputStream(this.getClientPath()+ File.separator+"ndn"+File.separator+"settings.properties"));
// 加载可修改属性的配置文件
public void loadSettingProperties() {
InputStream inputStream = null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream = new BufferedInputStream(new FileInputStream(this.getClientPath() + File.separator + "ndn" + File.separator + "settings.properties"));
// inputStream = MainApp.class.getClassLoader().getResourceAsStream("/ndn/settings.properties");
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
String serverIPAddress = settingProperties.getProperty("ServerIPAddress");
String serverPortAddress=settingProperties.getProperty("ServerPortAddress");
String dataPackagePrefix=settingProperties.getProperty("DataPackagePrefix");
System.out.println("ServerIPAddress: "+serverIPAddress);
System.out.println("ServerPortAddress: "+serverPortAddress);
System.out.println("DataPackagePrefix: "+dataPackagePrefix);
this.minoaServerIpString=serverIPAddress;
this.minoaServerPortInteger=Integer.parseInt(serverPortAddress);
this.globalPrefixString=dataPackagePrefix;
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
String serverIPAddress = settingProperties.getProperty("ServerIPAddress");
String serverPortAddress = settingProperties.getProperty("ServerPortAddress");
String NDNBlockChainIPAddressString=settingProperties.getProperty("ndnBlockChainIPAddress");
String NDNBlockChainPortAddressString=settingProperties.getProperty("ndnBlockChainPortAddress");
String dataPackagePrefix = settingProperties.getProperty("DataPackagePrefix");
String threadNumberString = settingProperties.getProperty("ThreadNumberForFileTransfer");
System.out.println("ServerIPAddress: " + serverIPAddress);
System.out.println("ServerPortAddress: " + serverPortAddress);
System.out.println("NDNBlockChainIPAddress: "+NDNBlockChainIPAddressString);
System.out.println("NDNBlockChainPortAddress: "+NDNBlockChainPortAddressString);
System.out.println("DataPackagePrefix: " + dataPackagePrefix);
System.out.println("ThreadNumberString: " + threadNumberString);
this.minoaServerIpString = serverIPAddress;
this.minoaServerPortInteger = Integer.parseInt(serverPortAddress);
this.NDNBlockChainIPAddress=NDNBlockChainIPAddressString;
this.NDNBlockChainPortAddress=Integer.parseInt(NDNBlockChainPortAddressString);
this.globalPrefixString = dataPackagePrefix;
this.threadNumberForFileTransfer = Integer.parseInt(threadNumberString);
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 获取一个新的数据请求标识
public Long getNewDataReqId() {
dataReqId++;
return dataReqId;
}
// 获取一个新的数据请求标识
public static Long getNewDataReqId() {
return dataReqId.incrementAndGet();
}
// 获取项目根目录路径
public String getClientPath() {
public static String getClientPath() {
File directory = new File("");// 参数为空
String path = "";
try {
@@ -266,60 +286,132 @@ public class MainApp extends Application {
minoaDataAPI.bindNews();
}
// 判断minoaAPI中的face是否启动,如果未开启,说明IP有问题,返回false
public static boolean isFaceLinked(){
return minoaDataAPI.runFace();
}
// 下载文件到本地缺省目录下[E盘根目录]
public Integer downloadFileByPathfilename(String pathfileName) {
return loginerController.downloadFile(pathfileName);
}
// public Integer downloadFileByPathfilename(String pathfileName) {
// return loginerController.downloadFile(pathfileName);
// }
// 登录失效:弹窗提醒,点击确定之后跳转到登录界面
public void reLogin(){
// 非FX线程调用FX的UI组件
Platform.runLater(() -> {
// 首先,修改本地登录状态
KeepLoginStatus.setLoginStatus(false);
// 然后,弹窗提醒
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("登录状态失效");
alert.setHeaderText("登录状态失效");
alert.setContentText("您的登录状态失效,请重新登录。");
alert.showAndWait();
// 最后,展示登录界面
showLoginOverview();
});
}
// 下载文件到指定目录下
public Integer downloadFileByPathfilename(String pathfileName, String localDir) {
return loginerController.downloadFileToSpecifiedDir(pathfileName, localDir);
}
// public Integer downloadFileByPathfilename(String pathfileName, String localDir) {
// return loginerController.downloadFileToSpecifiedDir(pathfileName, localDir);
// }
// 显示进度条并下载文件到指定目录下
public void downloadFileByPathfilenameWithProgressBar(String pathfileName, String localDir){
isCancelFileTransferFlag=false;
// 显示进度条并下载文件到指定目录下
public void downloadFileByPathfilenameWithProgressBar(String pathfileName, String localDir) {
// currentDownloadedDataSlices.set(0);
isCancelFileTransferFlag = false;
// 创建进度条子Stage
downloadFileDialogStage = new Stage();
downloadFileDialogStage.setTitle("minoaClientWindows-文件传输");
downloadFileDialogStage.setTitle("FileSystem-文件传输");
downloadFileDialogStage.getIcons().add(new Image("file:resources/images/logo_mini.png"));
downloadFileDialogStage.initStyle(StageStyle.TRANSPARENT);
downloadFileDialogStage.initModality(Modality.WINDOW_MODAL);
downloadFileDialogStage.initOwner(primaryStage);
Group root = new Group();
Scene scene = new Scene(root, 330, 120, Color.WHITE);
Scene scene = new Scene(root, 530, 220, Color.WHITE);
downloadFileDialogStage.setScene(scene);
BorderPane mainPane = new BorderPane();
mainPane.setPrefHeight(100);
mainPane.setPrefWidth(325);
mainPane.setPrefHeight(200);
mainPane.setPrefWidth(525);
root.getChildren().add(mainPane);
final Label label = new Label("文件传输进度:");
final ProgressBar progressBar = new ProgressBar(0);
progressBar.setPrefWidth(300);
Long filelen=loginerController.getServerFileLength(pathfileName);
Integer cycle = (int)(filelen / sliceSize);
if (filelen % sliceSize != 0) {
cycle++;
}
final Integer sliceNum=cycle;
// final Text text = new Text("0/" + cycle.toString());
final Text text = new Text("0%");
text.setWrappingWidth(50);
Text nullTextTop=new Text("");//空text,控制位置
Text nullTextLeft=new Text("");//空text,控制位置
// 文件名称
final Label filenamelabel = new Label("文件名称:");
final Text filenameText = new Text();
String filename=pathfileName;
if(filename.length()>50){
filename=filename.substring(0,50)+"...";
}
filenameText.setText(filename);
final HBox fnhb = new HBox();
fnhb.setSpacing(10);
fnhb.setAlignment(Pos.CENTER_LEFT);
fnhb.getChildren().addAll(filenamelabel, filenameText);
// 文件大小
final Label filesizeLabel = new Label("文件大小:");
final Text filesizeText = new Text();
String filesize= FileUtil.sizeToShowSize((long)filelen);
filesizeText.setText(filesize);
final HBox fshb = new HBox();
fshb.setSpacing(10);
fshb.setAlignment(Pos.CENTER_LEFT);
fshb.getChildren().addAll(filesizeLabel, filesizeText);
// fshb.setLayoutX(50);
// 两个合并
final VBox vb=new VBox();
vb.setSpacing(25);
vb.setAlignment(Pos.CENTER_LEFT);
vb.getChildren().addAll(nullTextTop,fnhb,fshb);
HBox bigHb=new HBox();
bigHb.setSpacing(38);
bigHb.setAlignment(Pos.CENTER_LEFT);
bigHb.getChildren().setAll(nullTextLeft,vb);
// vb.setLayoutX(50);
mainPane.setTop(bigHb);
final HBox hb = new HBox();
hb.setSpacing(20);
hb.setSpacing(10);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(label, progressBar);
hb.getChildren().addAll(label, progressBar,text);
mainPane.setCenter(hb);
final Button startButton = new Button("开始传输");
final Button cancelButton = new Button("取消传输");
final Button sureButton = new Button("确认完成");
sureButton.setDisable(true);
final HBox hb2 = new HBox();
hb2.setSpacing(20);
hb2.setSpacing(50);
hb2.setAlignment(Pos.CENTER);
// hb2.getChildren().addAll(startButton);
hb2.getChildren().addAll(startButton, cancelButton);
hb2.getChildren().addAll(startButton, cancelButton,sureButton);
mainPane.setBottom(hb2);
startButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
startButton.setDisable(true);
progressBar.setProgress(0);
cancelButton.setDisable(true);
cancelButton.setText("确认完成");
copyWorker = createDownWorker(pathfileName, localDir,cancelButton);
cancelButton.setDisable(false);
sureButton.setDisable(true);
copyWorker = createDownWorkerBasedWindow(pathfileName, localDir,sliceNum, cancelButton,sureButton,text);
progressBar.progressProperty().unbind();
progressBar.progressProperty().bind(copyWorker.progressProperty());
copyWorker.messageProperty().addListener(new ChangeListener<String>() {
@@ -333,237 +425,315 @@ public class MainApp extends Application {
});
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
if(cancelButton.getText().equals("确认完成")){
}else{
isCancelFileTransferFlag=true;
}
isCancelFileTransferFlag = true;
downloadFileDialogStage.close();
}
});
sureButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
downloadFileDialogStage.close();
// startButton.setDisable(false);
// cancelButton.setDisable(true);
// copyWorker.cancel(true);
// progressBar.progressProperty().unbind();
// progressBar.setProgress(0);
// System.out.println("传输已终止。");
}
});
// 打开文件传输Stage
downloadFileDialogStage.showAndWait();
}
// 文件数据下载TASK
public Task createDownWorker(String filename, String localDir,Button button) {
// 文件数据下载TASK:滑动窗口
public Task createDownWorkerBasedWindow(String filename, String localDir,Integer sliceNum, Button button,Button sureButton,Text text) {
return new Task() {
@Override
protected Object call() throws Exception {
// 下载到本地的文件名称
String localName = loginerController.getPureFileName(filename);
// 发送数据请求
Long seqLong = getNewDataReqId();
OrderInfo orderInfo=new OrderInfo();
orderInfo.setSeq(seqLong);
orderInfo.setJsonString(loginerController.getFileInfoJson(filename));
minoaDataAPI.executeOrder("/fileInfo", orderInfo);
// 获取文件信息
ResponseData responseData = minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
JSONObject jsonObject = responseData.praseRequestData();
System.out.println("fileInfo-JSON: " + jsonObject.toString());
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (codeInteger == 200) {
String dataString;
try {
dataString = jsonObject.getString("data");
JSONObject dataJsonObject = new JSONObject(dataString);
Integer sliceNumInteger;
sliceNumInteger = dataJsonObject.getInt("sliceNum");
// 根据分片信息获取每个分片,并合并成一个完整比特流
Integer flagSuccessInteger=0;
Integer flagInteger = 0;
for (int i = 0; i < sliceNumInteger; i++) {
flagInteger = loginerController.downLoadFileBySlice(filename, i, localDir, localName);
if(flagInteger==0){
flagSuccessInteger++;
System.out.println("数据分片"+i+"传输成功. ");
// updateMessage("");
updateProgress(flagSuccessInteger, sliceNumInteger);
}else{
flagSuccessInteger++;
System.out.println("数据分片"+i+"传输失败. ");
// updateMessage("");
updateProgress(flagSuccessInteger, sliceNumInteger);
Long startTime = System.currentTimeMillis();
// 滑动窗口协议下载文件
// DownLoadClient downLoadClient = new DownLoadClient(filename,localDir,sliceNum);
DownLoadClientBasedFacePool downLoadClient=new DownLoadClientBasedFacePool(filename,
localDir,sliceNum,threadNumberForFileTransfer);
//启动一个线程监听更新的传输进度值
Thread listenThread = new Thread(new Runnable() {
@Override
public void run() {
Long sliceNumLong=sliceNum.longValue();
// TODO Auto-generated method stub
while (true) {
Long progressInteger = downLoadClient.recvCount.get();
System.out.println("当前已经下载的数据片个数:" + progressInteger);
Double progressPercentDouble=Math.floor((progressInteger*100)/sliceNumLong);
Integer progressPercentInteger=progressPercentDouble.intValue();
String textString=progressPercentInteger.toString()+"%";
// 更新进度条
// String textString=progressInteger.toString()+ "/" + sliceNumLong.toString();
if (!text.getText().equals(textString)) {
updateProgress(progressInteger, sliceNumLong);
text.setText(textString);
}
//如果当前进度条
if (progressInteger.equals(sliceNumLong)) {
updateProgress(1,1);
text.setText("100%");
System.out.println("***************监听进度条的线程结束监听*************");
break;
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
text.setText("100%");
updateProgress(1,1);
System.out.println("***************监听进度条的线程结束监听*************");
break;
}
}
if(flagSuccessInteger==sliceNumInteger){
System.out.println("文件数据已成功全部写入本地");
}else{
System.out.println("由于未知原因,文件数据全部或部分未成功写入本地");
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
listenThread.start();
// 下载文件
boolean res = downLoadClient.downloadData();
listenThread.interrupt();
Long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - startTime) + "ms");
LoggerUtil.insertFileAction(filename,"下载",(endTime - startTime) + "ms");
// 每个分片都上传成功
if (res) {
System.out.println("已成功将文件 " + filename + " 下载到本地" + localDir + "目录下。");
} else {
System.out.println("由于未知原因,服务器端文件" + filename + "下载失败。");
}
//设置确认按钮
button.setDisable(false);
button.setDisable(true);
sureButton.setDisable(false);
return true;
}
};
}
// 上传本地文件到指定的服务器目录下
public Integer uploadFileToServerPath(File file, String serverpath) {
Integer r=loginerController.sendFileToServer(file, serverpath);
return r;
}
// public Integer uploadFileToServerPath(File file, String serverpath) {
// Integer r=loginerController.sendFileToServer(file, serverpath);
// return r;
// }
// 显示进度条并上传文件到指定目录
public void uploadFileToServerPathWithProgressBar(File file, String serverpath){
isCancelFileTransferFlag=false;
// 创建进度条子Stage
uploadFileDialogStage = new Stage();
uploadFileDialogStage.setTitle("minoaClientWindows-文件传输");
uploadFileDialogStage.getIcons().add(new Image("file:resources/images/logo_mini.png"));
uploadFileDialogStage.initStyle(StageStyle.TRANSPARENT);
uploadFileDialogStage.initModality(Modality.WINDOW_MODAL);
uploadFileDialogStage.initOwner(primaryStage);
public void uploadFileToServerPathWithProgressBar(File file, String serverpath) {
// currentUploadedDataSlices.set(0);
isCancelFileTransferFlag = false;
// 创建进度条子Stage
uploadFileDialogStage = new Stage();
uploadFileDialogStage.setTitle("FileSystemWindows-文件传输");
uploadFileDialogStage.getIcons().add(new Image("file:resources/images/logo_mini.png"));
uploadFileDialogStage.initStyle(StageStyle.TRANSPARENT);
uploadFileDialogStage.initModality(Modality.WINDOW_MODAL);
uploadFileDialogStage.initOwner(primaryStage);
Group root = new Group();
Scene scene = new Scene(root, 330, 120, Color.WHITE);
uploadFileDialogStage.setScene(scene);
Group root = new Group();
Scene scene = new Scene(root, 530, 220, Color.WHITE);
uploadFileDialogStage.setScene(scene);
BorderPane mainPane = new BorderPane();
mainPane.setPrefHeight(100);
mainPane.setPrefWidth(325);
root.getChildren().add(mainPane);
BorderPane mainPane = new BorderPane();
mainPane.setPrefHeight(200);
mainPane.setPrefWidth(525);
root.getChildren().add(mainPane);
final Label label = new Label("文件传输进度:");
final ProgressBar progressBar = new ProgressBar(0);
Text nullTextTop=new Text("");//空text,控制位置
Text nullTextLeft=new Text("");//空text,控制位置
// 文件名称
final Label filenamelabel = new Label("文件名称:");
final Text filenameText = new Text();
String filename=file.getAbsolutePath();
if(filename.length()>50){
filename=filename.substring(0,50)+"...";
}
filenameText.setText(filename);
final HBox fnhb = new HBox();
fnhb.setSpacing(10);
fnhb.setAlignment(Pos.CENTER_LEFT);
fnhb.getChildren().addAll(filenamelabel, filenameText);
// 文件大小
final Label filesizeLabel = new Label("文件大小:");
final Text filesizeText = new Text();
String filesize= FileUtil.sizeToShowSize(file.length());
filesizeText.setText(filesize);
final HBox fshb = new HBox();
fshb.setSpacing(10);
fshb.setAlignment(Pos.CENTER_LEFT);
fshb.getChildren().addAll(filesizeLabel, filesizeText);
// fshb.setLayoutX(50);
// 两个合并
final VBox vb=new VBox();
vb.setSpacing(25);
vb.setAlignment(Pos.CENTER_LEFT);
vb.getChildren().addAll(nullTextTop,fnhb,fshb);
HBox bigHb=new HBox();
bigHb.setSpacing(38);
bigHb.setAlignment(Pos.CENTER_LEFT);
bigHb.getChildren().setAll(nullTextLeft,vb);
// vb.setLayoutX(50);
mainPane.setTop(bigHb);
final HBox hb = new HBox();
hb.setSpacing(20);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(label, progressBar);
mainPane.setCenter(hb);
final Label label = new Label("文件传输进度:");
final ProgressBar progressBar = new ProgressBar(0);
progressBar.setPrefWidth(300);
// long filelen = file.length();
// int cycle = (int) (filelen / sliceSize);
// if (filelen % sliceSize != 0) {
// cycle++;
// }
// final Text text = new Text("0/" + cycle);
final Text text = new Text("0%" );
text.setWrappingWidth(50);
final HBox hb = new HBox();
hb.setSpacing(10);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(label, progressBar, text);
mainPane.setCenter(hb);
final Button startButton = new Button("开始传输");
final Button cancelButton = new Button("取消传输");
final HBox hb2 = new HBox();
hb2.setSpacing(20);
hb2.setAlignment(Pos.CENTER);
final Button startButton = new Button("开始传输");
final Button cancelButton = new Button("取消传输");
final Button sureButton = new Button("确认完成");
sureButton.setDisable(true);
final HBox hb2 = new HBox();
hb2.setSpacing(50);
hb2.setAlignment(Pos.CENTER);
// hb2.getChildren().addAll(startButton);
hb2.getChildren().addAll(startButton, cancelButton);
mainPane.setBottom(hb2);
startButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
startButton.setDisable(true);
progressBar.setProgress(0);
cancelButton.setDisable(true);
cancelButton.setText("确认完成");
copyWorker = createWorker(file, serverpath,cancelButton);
progressBar.progressProperty().unbind();
progressBar.progressProperty().bind(copyWorker.progressProperty());
copyWorker.messageProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
System.out.println(newValue);
}
});
new Thread(copyWorker).start();
}
});
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
if(cancelButton.getText().equals("确认完成")){
}else{
isCancelFileTransferFlag=true;
hb2.getChildren().addAll(startButton, cancelButton,sureButton);
mainPane.setBottom(hb2);
startButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
startButton.setDisable(true);
progressBar.setProgress(0);
cancelButton.setDisable(false);
// copyWorker = createWorker(file, serverpath, cancelButton, text);
copyWorker = createUploadWorkerBasedWindow(file, serverpath, cancelButton, sureButton,text);
progressBar.progressProperty().unbind();
progressBar.progressProperty().bind(copyWorker.progressProperty());
copyWorker.messageProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
System.out.println(newValue);
}
uploadFileDialogStage.close();
// startButton.setDisable(false);
// cancelButton.setDisable(true);
// copyWorker.cancel(true);
// progressBar.progressProperty().unbind();
// progressBar.setProgress(0);
// System.out.println("传输已终止。");
}
});
// 打开文件传输Stage
uploadFileDialogStage.showAndWait();
});
new Thread(copyWorker).start();
}
});
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
// 手动取消了传输
isCancelFileTransferFlag = true;
uploadFileDialogStage.close();
}
});
sureButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
// 确认完成了传输
uploadFileDialogStage.close();
}
});
// 打开文件传输Stage
uploadFileDialogStage.showAndWait();
// });
}
// 文件数据上传TASK
public Task createWorker(File file, String serverpath,Button button) {
// 文件数据上传TASK:滑动窗口
public Task createUploadWorkerBasedWindow(File file, String serverpath, Button button,Button sureButton, Text text) {
return new Task() {
@Override
protected Object call() throws Exception {
//获取要上传文件的文件长度,计算上传次数
long filelen = file.length();
int cycle = (int) filelen / sliceSize;
int remainder=(int)filelen%sliceSize;
if((cycle>0)&&(remainder==0)) {
cycle--;
int cycle = (int) (filelen / sliceSize);
if (filelen % sliceSize != 0) {
cycle++;
}
System.out.println("file-len: " + filelen);
System.out.println("cycle: " + cycle);
//发送上传命令给上传接口,接口自行取本地数据
int flagSuccess = 0; //记录收到200回复的次数
for (int i = 0; i <= cycle; i++) {
OrderInfo orderInfo = new OrderInfo();
ResponseData responseData = new ResponseData();
Long seqLong = getNewDataReqId();
orderInfo.setSeq(seqLong);
//此时传入的文件路径是windows下的绝对路径
orderInfo.setJsonString(loginerController.getUploadFile(file.getAbsolutePath(), i * sliceSize));
minoaDataAPI.executeOrder("/uploadFile", orderInfo, serverpath);
responseData = minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
// System.out.println("上传文件的数据回执(200表示成功)"+responseData.getResponseJsonDataString());
JSONObject jsonObject = responseData.praseRequestData();
responseData.printSelf();
// 解析数据
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Long startTime = System.currentTimeMillis();
// 滑动窗口协议上传文件
// UpLoadClient upLoadClient = new UpLoadClient(file, serverpath);
UpLoadClientBasedFacePool upLoadClient=new UpLoadClientBasedFacePool(file,
serverpath,threadNumberForFileTransfer);
//启动一个线程监听更新的传输进度值
Thread listenThread = new Thread(new Runnable() {
@Override
public void run() {
long filelen = file.length();
Long sliceNumLong = filelen / sliceSize;
if (filelen % sliceSize != 0) {
sliceNumLong++;
}
// TODO Auto-generated method stub
while (true) {
Long progressInteger = upLoadClient.recvCount.get();
System.out.println("当前已经上传的数据片个数:" + progressInteger);
Double progressPercentDouble=Math.floor((progressInteger*100)/sliceNumLong);
Integer progressPercentInteger=progressPercentDouble.intValue();
String textString=progressPercentInteger.toString()+"%";
// 更新进度条
// String textString=progressInteger.toString()+ "/" + cycleInteger;
if (!text.getText().equals(textString)) {
updateProgress(progressInteger, sliceNumLong);
text.setText(textString);
}
//如果当前进度条
if (progressInteger.equals(sliceNumLong)) {
text.setText("100%");
updateProgress(1,1);
System.out.println("***************监听进度条的线程结束监听*************");
break;
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
text.setText("100%");
updateProgress(1,1);
System.out.println("***************监听进度条的线程结束监听*************");
break;
}
}
}
if (codeInteger == 200) {
flagSuccess++;
System.out.println("数据分片"+i+"传输结果[200表示成功]: "+codeInteger);
// updateMessage("");
updateProgress(i + 1, cycle+1);
}else{
System.out.println("数据分片"+i+"传输结果[200表示成功]: "+codeInteger);
// updateMessage("");
updateProgress(i + 1, cycle+1);
}
}
//每个分片都上传成功
if (flagSuccess == (cycle + 1)) {
});
// 先发送一个开始上传信号
String serverFilePath = serverpath + MinoaDataAPI.getPureFileNameFromWindows(file.getAbsolutePath());
// ECOSUtil.sendUploadFileBeginSignal(serverFilePath);
listenThread.start();
// 上传文件
boolean res = upLoadClient.uploadData();
// 上传完成或取消上传后,取消上传进度监听
listenThread.interrupt();
Long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - startTime) + "ms");
LoggerUtil.insertFileAction(file.getAbsolutePath(),"上传",(endTime - startTime) + "ms");
// 每个分片都上传成功
if (res) {
System.out.println("已成功将文件" + file.getAbsolutePath() + "上传至服务器" + serverpath + "目录下。");
// String serverFilePath = serverpath + MinoaDataAPI.getPureFileNameFromWindows(file.getAbsolutePath());
// ECOSUtil.sendUploadFileEndSignal(serverFilePath);
} else {
System.out.println("由于未知原因,本地文件" + file.getAbsolutePath() + "上传服务器失败。");
}
//设置确认按钮
button.setDisable(false);
// System.out.println("文件上传线程:我干完活儿啦");
// 设置取消按钮状态
button.setDisable(true);
// 设置确认按钮状态
sureButton.setDisable(false);
return true;
}
};
}
// 上传本地文件到服务器的共享文件夹下
public Integer uploadFileToServerSharedFolder(File file) {
Integer res=loginerController.sendFileToServer(file, this.sharedFileServerPath);
public boolean uploadFileToServerSharedFolder(File file) {
// Integer res=loginerController.sendFileToServer(file, this.sharedFileServerPath);
Long startTime = System.currentTimeMillis();
UpLoadClientBasedFacePool upLoadClient = new UpLoadClientBasedFacePool(
file,this.sharedFileServerPath,threadNumberForFileTransfer);
// 下载文件
boolean res = ((UpLoadClientBasedFacePool) upLoadClient).uploadData();
Long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - startTime) + "ms");
return res;
}
//请求服务器某文件的字节长度
public Integer getServerFileByteLength(String filename){
public Long getServerFileByteLength(String filename){
return loginerController.getServerFileLength(filename);
}
@@ -709,27 +879,49 @@ public class MainApp extends Application {
showLoginOverview();
}
// 展示登录界面
public void showLoginOverview() {
try {
// 加载overview
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getClassLoader().getResource("fxml/login/LoginOverview.fxml"));
AnchorPane loginOverview = (AnchorPane) loader.load();
// 展示登录界面
public void showLoginOverview() {
try {
// 加载overview
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getClassLoader().getResource("fxml/login/LoginOverview.fxml"));
AnchorPane loginOverview = (AnchorPane) loader.load();
// 设置scene
Scene scene = new Scene(loginOverview);
primaryStage.setScene(scene);
// 设置scene
Scene scene = new Scene(loginOverview);
// 传参给控制器
loginerController = loader.getController();
loginerController.setMainApp(this);
// 传参给控制器
loginerController = loader.getController();
loginerController.setMainApp(this);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
// 判断是否是登录状态,且账号密码是正确的
boolean m_flag=false;
boolean isLoginning= KeepLoginStatus.getLogineStatus();
Loginer m_loginer=KeepLoginStatus.getLoginerInfo();
if((isLoginning==true)&&(m_loginer.getUserName()!=null)&&(m_loginer.getPassWord()!=null)){
System.out.println("login status: "+isLoginning);
System.out.println("loginer name: "+m_loginer.getUserName());
System.out.println("loginer password: "+m_loginer.getPassWord());
String loginString=loginerController.getLoginJsonString(
m_loginer.getUserName(),m_loginer.getPassWord());
if(loginerController.checkPass(loginString)){
m_flag=true;
}
}
if(m_flag){
// 是登录状态且账号密码正确
isNeedKnowLoginStatus=true;
iniShow();
}else{
// 否则
primaryStage.setScene(scene);
}
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
// 使用弹窗展示设置界面
public void showSettingOverview() {
@@ -0,0 +1,205 @@
package cn.minoa.dataRequestInterface;
/**
* @author mac
* @description
* 拥塞窗口
* @date 2020-03-24 10:25
*/
public class CongestionWindow {
//拥塞窗口大小
private Double cwnd;
//表示当前正在发送的数据,发送一条数据需要加一,收到成功恢复需要减一
private Double inFlight;
//拥塞窗口阈值
private Double thresh;
//下一次窗口减小的界限
private Integer nSupress = 0;
//收到数据包的数量,收到一个数据包进行加一操作
private Long nIndata = 0l;
//发送兴趣包的数量,发出一个兴趣包进行加一操作
private Long nOutInterest = 0l;
//更新nsupress时的一个比率
private static Double rate = 0.5d;
public CongestionWindow(){
this.cwnd = 4d;
this.thresh = 300d;
this.inFlight = 0d;
}
public CongestionWindow(Double cwnd, Double thresh, Double inFlight){
this.inFlight = inFlight;
this.cwnd = cwnd;
this.thresh = thresh;
}
/**
* 当前窗口是否为空
* @return
*/
public boolean empty(){
boolean res = false;
synchronized (this){
if (inFlight == 0){
res = true;
}
}
return res;
}
/**
* 当前窗口是否已满
* @return
*/
public boolean full(){
boolean res = false;
synchronized (this){
if(cwnd == inFlight){
res = true;
}
}
return res;
}
/**
* 获取当前还能发送多少数据
* 如果不能发送数据,返回值为0
* @return
*/
public int getAvailableCwnd(){
int res = 0;
synchronized (this){
if(inFlight >= cwnd){
res = 0;
}else{
res = (int)(cwnd - inFlight);
}
}
return res;
}
/**
* 在onData函数中
* 收到一个数据包,执行加一操作,需要加锁
*/
public void nIndataIncrease(){
synchronized (this){
nIndata++;
}
}
/**
* 发出一个兴趣包,执行加一操作,不需要加锁
*/
public void nOutInterestIncrease(){
nOutInterest++;
}
/**
* inFlight加一
*/
public void inFlightIncrease(){
synchronized (this){
this.inFlight++;
}
}
public void inFlightIncrease(int inFlight){
synchronized (this){
this.inFlight += inFlight;
}
}
/**
* inFliehgt减一
*/
public void inFlightDecrease(){
synchronized (this){
this.inFlight--;
}
}
public void inFlightDecrease(int inFlight){
synchronized (this){
this.inFlight -= inFlight;
}
}
/**
* 增加拥塞窗口的值
*
*/
public void cwndIncrease(){
synchronized (this){
if(this.cwnd < this.thresh){
//慢开始算法
this.cwnd += 1;
/*if(this.cwnd > this.thresh){
this.thresh = this.cwnd;
}*/
}else{
//拥塞避免算法
this.cwnd += (1.0/this.cwnd);
}
}
System.out.println("-----------------------------------------cwnd:" + cwnd + ", thresh:" + thresh);
}
/**
* 减少拥塞窗口的值
* 每当检测到拥塞时,就需要执行此函数
*/
public void cwndDecrease(){
synchronized (this){
if(nIndata >= nSupress){
this.thresh = Math.floor(this.cwnd/2);
this.cwnd = this.thresh;
nSupress = (int)(nOutInterest + rate*(nOutInterest - nIndata));
}
}
System.out.println("-----------------------------------------cwnd:" + cwnd + ", thresh:" + thresh);
}
/**
* 设置拥塞窗口大小
* @param cwnd
*/
public void setCwnd(Double cwnd){
synchronized (this){
this.cwnd = cwnd;
}
}
/**
* 获得当前拥塞窗口大小
* @return
*/
public Integer getCwnd(){
int res = 0;
synchronized (this){
res = this.cwnd.intValue();
}
return res;
}
@Override
public String toString() {
return "CongestionWindow {" +
"cwnd=" + cwnd +
", inFlight=" + inFlight +
", thresh=" + thresh +
'}';
}
}
@@ -2,28 +2,30 @@ package cn.minoa.dataRequestInterface;
//缓存服务器的回执数据
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
public class DataCacheQueue {
//存储数据回执
public Map<Long, ResponseData> responseDataMap;
// public static volatile Map<Long, ResponseData> responseDataMap;
public static volatile ConcurrentHashMap<Long, ResponseData> responseDataMap = new ConcurrentHashMap<Long, ResponseData>();
public DataCacheQueue() {
// TODO Auto-generated constructor stub
responseDataMap=new TreeMap<Long, ResponseData>();
// responseDataMap=new TreeMap<Long, ResponseData>();
responseDataMap=new ConcurrentHashMap<Long, ResponseData>();
}
//放入一个数据
public void setResponseData(Long seq,ResponseData rd) {
public static void setResponseData(Long seq,ResponseData rd) {
responseDataMap.put(seq, rd);
}
//根据seq获取ResponseData
public ResponseData getResponseDataBySeq(Long seq) {
public static ResponseData getResponseDataBySeq(Long seq) {
//等待数据回执
while(!responseDataMap.containsKey(seq)) {
try {
Thread.sleep(10);
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -33,11 +35,20 @@ public class DataCacheQueue {
responseDataMap.remove(seq);
return rd;
}
//判断是否为空
public boolean isEmpty() {
public static boolean isEmpty() {
return responseDataMap.isEmpty();
}
public static void showMapData(){
System.out.println("this is responseDataMap info:");
for(Map.Entry<Long, ResponseData> entry : responseDataMap.entrySet()){
System.out.println("entry-key:" + entry.getKey() + ", entry-value:");
entry.getValue().printSelf();
}
System.out.println("--------------- end ----------------");
}
}
@@ -1,133 +0,0 @@
package cn.minoa.dataRequestInterface;
import org.json.JSONObject;
import cn.minoa.MainApp;
public class DataTestMain {
//文件操作命令
static private String getFileActionJson(String uuid,String cmd) {
JSONObject jsonObject =new JSONObject();
String commandString="/fileAction";
String usernameString="wefree";
String uuidString=uuid;
String cmdString=cmd;
String filename="/";
try {
jsonObject.put("command", commandString);
jsonObject.put("username", usernameString);
jsonObject.put("uuid", uuidString);
jsonObject.put("fileCmd", cmdString);
jsonObject.put("filename", filename);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
//发送消息
static private String getSendRTMsgJson(String uuid,String msgTail) {
JSONObject jsonObject =new JSONObject();
String commandString="/sendRTMsg";
String fromString="oa_wefree";
String toString="wefree";
String uuidString=uuid;
String msgString="hello,wefree. iam oa_wefree. --"+msgTail;
try {
jsonObject.put("command", commandString);
jsonObject.put("from", fromString);
jsonObject.put("to", toString);
jsonObject.put("uuid", uuidString);
jsonObject.put("msg", msgString);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
//请求通知消息
static private String getGetInformJson(Integer pageNo,String uuidString) {
JSONObject jsonObject =new JSONObject();
String commandString="/getInform";
String usernameString="wefree";
Integer pageNoInteger=pageNo;
Integer pageSizeInteger=10;
try {
jsonObject.put("command", commandString);
jsonObject.put("username", usernameString);
jsonObject.put("uuid", uuidString);
jsonObject.put("pageNo", pageNoInteger);
jsonObject.put("pageSize", pageSizeInteger);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
public static void main(String args[]){
MainApp mainApp=new MainApp();
MinoaDataAPI minoaDataAPI=new MinoaDataAPI(mainApp);
//test register
// minoaDataAPI.executeOrder("/register", orderInfo);
//test login
OrderInfo loginOrderInfo=new OrderInfo();
loginOrderInfo.setSeq((long) 0);
loginOrderInfo.setLoginJson();
minoaDataAPI.executeOrder("/login", loginOrderInfo);
ResponseData responseData=minoaDataAPI.dataCacheQueue.getResponseDataBySeq((long) 0);
responseData.printSelf();
String uuidString=responseData.getUuidByPraseLoginData();
//test getUsers
// minoaDataAPI.executeOrder("/getUsers", orderInfo);
//test sendRTMsg
// minoaDataAPI.executeOrder("/sendRTMsg", orderInfo);
//test getRTMsg
// minoaDataAPI.executeOrder("/getRTMsg", orderInfo);
//test getRTMsgLog
// minoaDataAPI.executeOrder("/getRTMsgLog", orderInfo);
//制造点假数据出来[wefree=>oa_wefree]
// OrderInfo orderInfo=new OrderInfo();
// String sendJsonString;
// for(int i=1;i<5;i++) {
// orderInfo.setSeq((long) i);
// sendJsonString=getSendRTMsgJson(uuidString,String.valueOf(i));
// orderInfo.setJsonString(sendJsonString);
// minoaDataAPI.executeOrder("/sendRTMsg", orderInfo);
// responseData=minoaDataAPI.dataCacheQueue.getResponseDataBySeq((long) i);
// responseData.printSelf();
// }
//测试请求通知信息
// OrderInfo orderInfo=new OrderInfo();
// orderInfo.setSeq((long)1);
// orderInfo.setJsonString(getGetInformJson(0,uuidString));
// minoaDataAPI.executeOrder("/getInform", orderInfo);
// responseData=minoaDataAPI.dataCacheQueue.getResponseDataBySeq((long) 1);
// responseData.printSelf();
//测试云文件上传下载
OrderInfo orderInfo=new OrderInfo();
orderInfo.setSeq((long)1);
orderInfo.setJsonString(getFileActionJson(uuidString, "ls"));
minoaDataAPI.executeOrder("/fileAction", orderInfo);
responseData=minoaDataAPI.dataCacheQueue.getResponseDataBySeq((long) 1);
responseData.printSelf();
orderInfo.setSeq((long)2);
orderInfo.setJsonString(getFileActionJson(uuidString, "rm"));
minoaDataAPI.executeOrder("/fileAction", orderInfo);
responseData=minoaDataAPI.dataCacheQueue.getResponseDataBySeq((long) 2);
responseData.printSelf();
orderInfo.setSeq((long)3);
orderInfo.setJsonString(getFileActionJson(uuidString, "mkdir"));
minoaDataAPI.executeOrder("/fileAction", orderInfo);
responseData=minoaDataAPI.dataCacheQueue.getResponseDataBySeq((long) 3);
responseData.printSelf();
}
}
@@ -0,0 +1,71 @@
package cn.minoa.dataRequestInterface;
// 多线程上传下载:数据收发接口【3/3】
import cn.minoa.MainApp;
import org.json.JSONObject;
/**
* @author mac
* @description
* @date 2020-03-16 11:16
*/
public class DownAndUpLoadData {
/**
* 构造下载文件的json信息
* @param filename
* @param sliceNo
* @return
*/
public static String getDownloadFileJson(String filename, Integer sliceNo) {
JSONObject jsonObject = new JSONObject();
String commandString;
if(filename.contains("/")){
commandString = "/downloadFile";
}else{
commandString="/downloadShareFile";
}
String usernameString = MainApp.loginer.getUserName();
String uuidString = MainApp.loginer.getUuid();
String filenameString = filename;
Integer sliceNoInteger = sliceNo;
try {
jsonObject.put("command", commandString);
jsonObject.put("username", usernameString);
jsonObject.put("uuid", uuidString);
jsonObject.put("filename", filenameString);
jsonObject.put("sliceNo", sliceNoInteger);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
System.out.println("getDownloadFileJson: "+jsonObject.toString());
return jsonObject.toString();
}
/**
* 构造上传文件的json字符串
* @param filename
* @param offset
* @return
*/
public static String getUploadFile(String filename, Long offset) {
JSONObject jsonObject = new JSONObject();
String commandString = "/uploadFile";
String usernameString = MainApp.loginer.getUserName();
String uuidString = MainApp.loginer.getUuid();
String filenameString = filename;
Long offsetInteger = offset;
try {
jsonObject.put("command", commandString);
jsonObject.put("username", usernameString);
jsonObject.put("uuid", uuidString);
jsonObject.put("filename", filenameString);
jsonObject.put("offset", offsetInteger);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
}
@@ -0,0 +1,331 @@
package cn.minoa.dataRequestInterface;
import cn.minoa.MainApp;
import net.named_data.jndn.*;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.SecurityException;
import net.named_data.jndn.security.pib.PibImpl;
import net.named_data.jndn.util.Blob;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author mac
* @description
* @date 2020-03-22 18:28
*/
public class DownLoadClientBasedFacePool {
// 下载前缀
private String orderPrefix = "/downloadFile";
// 要下载的文件的服务器路径
private String filename;
// 下载到的文件路径
private String localDir;
// 要下载的文件的总数据片个数
private Integer sliceNumber;
// 当前排到应该下载的数据片序号
private Integer currentSliceNo = 0;
// FacePool
private FacePool facePool;
// 下载到本地的文件对象
private RandomAccessFile randomAccessFile;
// 滑动窗口控制类
private CongestionWindow congestionWindow = new CongestionWindow();
// 存放发送失败数据的文件偏移
private ConcurrentLinkedQueue<Integer> failedSlice = new ConcurrentLinkedQueue<>();
// 收到回复的数量
public AtomicLong recvCount = new AtomicLong(0);
//发送的数据是否发送成功,key:第几个数据片,从0开始,value:该数据片超时次数
private Map<Integer, Integer> timeOutNums = new ConcurrentHashMap<>();
// 超时重传上限数值,某个兴趣包的重传次数超过此数值,则放弃重传,直接返回false
private Integer timeoutCeil=15;
public DownLoadClientBasedFacePool(String filename, String localDir,
Integer sliceNumber, Integer facepoolnumber) {
this.filename = filename;
this.localDir = localDir;
System.out.println("localDir: "+this.localDir);
this.sliceNumber = sliceNumber;
this.facePool=new FacePool(facepoolnumber);
this.facePool.start(MinoaDataAPI.minoaServerIpString, MinoaDataAPI.minoaServerPortInteger);
System.out.println("***********FacePool中并发数:"+facepoolnumber+"***********");
}
/**
* 判断是否含有超时次数超过阈值的
* @return
*/
private boolean isTimeOut(){
for (Map.Entry<Integer, Integer> entry : timeOutNums.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
if(entry.getValue() > timeoutCeil){
return true;
}
}
return false;
}
/**
* 下载数据的主函数
*
* @return
*/
public boolean downloadData() {
// 先初始化一个本地文件
try {
String localName= MinoaDataAPI.getPureFileName(filename);
this.randomAccessFile = new RandomAccessFile(localDir + localName, "rw");
System.out.println("本地文件打开");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (true) {
//判断是否已经上传安成
if (recvCount.longValue()>=this.sliceNumber) {
break;
}
// 判断是否已经被用户终止上传
if(MainApp.isCancelFileTransferFlag){
System.out.println("用户已主动中断下载");
try {
this.randomAccessFile.close();
System.out.println("本地文件关闭");
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
// 每一次发送数据
int cwnd = 0;
// 获取此次可以发送数据的个数
while ((cwnd = congestionWindow.getAvailableCwnd()) <= 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < cwnd; i++) {
//TODO 首先发送failedmap中的数据
if (failedSlice.size() > 0) {
//首先发送failedslice中的数据
Integer failSliceNo = failedSlice.poll();
System.out.println("发送数据, name: " + filename + ", failSliceNo:" + failSliceNo+ ", failedSlice Size:" + failedSlice.size());
recvData(failSliceNo);
} else {
if (this.currentSliceNo < this.sliceNumber) {
System.out.println("发送数据, name: " + filename + "current SliceNo" + currentSliceNo + ", failedSlice Size:" + failedSlice.size());
recvData(currentSliceNo);
currentSliceNo++;
}
}
}
if(isTimeOut()){
System.out.println("丢包超过阈值: "+timeoutCeil+" ,文件传输主动中断");
this.facePool.shutdownNow();
try {
this.randomAccessFile.close();
System.out.println("本地文件关闭");
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
this.facePool.shutdownNow();
try {
this.randomAccessFile.close();
System.out.println("本地文件关闭");
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
/**
* 下载一个数据片
*
* @param sliceNo
*/
private void recvData(Integer sliceNo) {
facePool.submit(freeface -> {
// 设置JSON请求命令
OrderInfo orderInfo = new OrderInfo();
Long seqLong = MainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
String testStr = DownAndUpLoadData.getDownloadFileJson(filename, sliceNo);
System.out.println("*******************DownloadJson:" + testStr + "*******************");
orderInfo.setJsonString(testStr);
// 发送兴趣包
Name name = new Name(MinoaDataAPI.globalPrefixString + orderPrefix + "/" + seqLong);
Interest interest = new Interest(name);
interest.setMustBeFresh(true);
interest.setInterestLifetimeMilliseconds(5000);
try {
ResponseData responseData = new ResponseData();
responseData.setPrefix(orderPrefix);
// 签名
try {
// 赋值兴趣包的附带信息,并标志区块链
interest.setApplicationParameters(new Blob(orderInfo.getJsonString()));
KeyManager.INSTANCE.getKeyChain().sign(interest);
// MinoaDataAPI.keyChain.sign(interest);
} catch (PibImpl.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyChain.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (net.named_data.jndn.security.tpm.TpmBackEnd.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String purefilename = MinoaDataAPI.getPureFileName(filename);
DownLoadData downLoadData = new DownLoadData(this.localDir, purefilename, sliceNo);
// 使用tcp发送数据请求兴趣包
freeface.expressInterest(interest, downLoadData, downLoadData, downLoadData);
// 滑动窗口:flight++
congestionWindow.inFlightIncrease();
// 滑动窗口:outInterest++
congestionWindow.nOutInterestIncrease();
} catch (IOException e) {
e.printStackTrace();
}
});
}
public class DownLoadData implements OnData, OnTimeout, OnNetworkNack {
// 下载到的本地路径
private String localDir;
//下载到本地后重命名的文件名称
private String localName;
// 下载到本地路径后的文件名称
private Integer sliceNo;
// 标记是否拿到网络回复(数据信息/超时信息)
public boolean isFinished = false;
public DownLoadData(String localDir,String localName, Integer sliceNo) {
this.localDir = localDir;
this.localName = localName;
this.sliceNo = sliceNo;
}
@Override
public void onData(Interest interest, Data data) {
// 将文件数据片写入本地文件
try {
synchronized (randomAccessFile) {
System.out.println("开始写入文件数据分片... :" + localDir + localName);
// RandomAccessFile randomAccessFile = new RandomAccessFile(localDir + localName, "rw");
// int contentSize = data.getContent().size();
// System.out.println("该数据分片长度为:" + contentSize);
// byte[] content = new byte[contentSize];
// for (int i = 0; i < contentSize; i++) {
// content[i] = data.getContent().buf().get(i);
// }
// 设置数据分片写入到文件的起点位置
randomAccessFile.seek(sliceNo * MainApp.sliceSize);
// 写入数据分片
randomAccessFile.write(data.getContent().getImmutableArray());
// randomAccessFile.write(content, 0, contentSize);
// randomAccessFile.close();
System.out.println("写入文件数据分片完毕:" + localDir + localName);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 滑动窗口:flight--
congestionWindow.inFlightDecrease();
// 收到成功数据的数量++
recvCount.incrementAndGet();
// 滑动窗口:inData++
congestionWindow.nIndataIncrease();
System.out.println("" + sliceNo + "片下载成功!");
// 处理拥塞:拥塞标记返回值,无意义,大于0就表示拥塞,直接进行窗口减小操作即可
if (data.getCongestionMark() > 0) {
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&网络拥塞,滑动窗口减小,getCongestionMark" + data.getCongestionMark());
// 滑动窗口:cwndDecrease()
congestionWindow.cwndDecrease();
}else{
// 滑动窗口:cwndIncrease()
congestionWindow.cwndIncrease();
}
if(timeOutNums.containsKey(this.sliceNo)){
timeOutNums.remove(this.sliceNo);
}
// 处理完成
isFinished = true;
}
// 处理兴趣包超时
@Override
public void onTimeout(Interest interest) {
// 滑动窗口:flight--
congestionWindow.inFlightDecrease();
// 加入失败队列
failedSlice.add(sliceNo);
// 打印超时信息
System.out.println("########## Time out for interest " + interest.getName()+"###########");
if(timeOutNums.containsKey(this.sliceNo)){
int value = timeOutNums.get(this.sliceNo) + 1;
timeOutNums.put(this.sliceNo,value);
}else{
timeOutNums.put(this.sliceNo,1);
}
// 处理完成
isFinished = true;
}
// 处理收到一个Nack包
@Override
public void onNetworkNack(Interest interest, NetworkNack networkNack){
congestionWindow.inFlightDecrease();
failedSlice.add(sliceNo);
if(timeOutNums.containsKey(this.sliceNo)){
int value = timeOutNums.get(this.sliceNo) + 1;
timeOutNums.put(this.sliceNo,value);
}else{
timeOutNums.put(this.sliceNo,1);
}
// 打印超时信息
System.out.println("########## Nack for interest " + interest.getName()
+", Nack: "+networkNack.toString());
isFinished=true;
}
}
}
@@ -0,0 +1,162 @@
package cn.minoa.dataRequestInterface;
import net.named_data.jndn.Face;
import net.named_data.jndn.encoding.EncodingException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Face 池,里面可以创建多个face连接,每个face单独一个线程处理
*/
public class FacePool {
private int poolSize;
// 采用阻塞队列来记录任务
private LinkedBlockingQueue<Face> faceLinkedBlockingQueue;
private ArrayList<Face> faces;
private ExecutorService processEventThreadPool;
private ExecutorService faceDealThreadPool;
public FacePool(int poolSize) {
this.poolSize = poolSize;
faces = new ArrayList<>();
processEventThreadPool = Executors.newFixedThreadPool(poolSize);
faceDealThreadPool = Executors.newFixedThreadPool(poolSize);
faceLinkedBlockingQueue = new LinkedBlockingQueue<>();
}
public FacePool start(String host, int port) {
for (int i = 0; i < poolSize; i++) {
faces.add(new Face(host, port));
final int finalI = i;
ProcessEventTask processEventTask = new ProcessEventTask(host, port, faces.get(i), i, task -> {
// 发生错误则自动重新创建face,建立连接,然后将processEvent任务提交到线程池当中
processEventThreadPool.submit(task);
faces.set(finalI, task.getFace());
});
processEventThreadPool.submit(processEventTask);
// 初始时Face池里所有的Face都是可用的
faceLinkedBlockingQueue.add(faces.get(i));
}
return this;
}
public FacePool submit(AsyncUseFaceCallback asyncUseFaceCallback) {
faceDealThreadPool.submit(() -> {
try {
Face face = faceLinkedBlockingQueue.take();
asyncUseFaceCallback.onFaceAvailable(face);
faceLinkedBlockingQueue.put(face);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return this;
}
public void shutdownNow() {
if (!processEventThreadPool.isShutdown()) {
processEventThreadPool.shutdownNow();
}
if (!faceDealThreadPool.isShutdown()) {
faceDealThreadPool.shutdown();
}
}
///////////////////////////////////////////////////////////////////////////////////////////
///// Callback
///////////////////////////////////////////////////////////////////////////////////////////
public interface AsyncUseFaceCallback {
void onFaceAvailable(Face face);
}
///////////////////////////////////////////////////////////////////////////////////////////
///// Tasks
///////////////////////////////////////////////////////////////////////////////////////////
static class ProcessEventTask implements Runnable {
private Face face;
private int id;
private String host;
private int port;
private StatusCallback statusCallback;
public ProcessEventTask(String host, int port, Face face, int id, StatusCallback statusCallback) {
this.face = face;
this.id = id;
this.host = host;
this.port = port;
this.statusCallback = statusCallback;
}
public Face getFace() {
return face;
}
public void setFace(Face face) {
this.face = face;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public StatusCallback getStatusCallback() {
return statusCallback;
}
public void setStatusCallback(StatusCallback statusCallback) {
this.statusCallback = statusCallback;
}
@Override
public void run() {
// System.out.println("faceId: " + id + "(host: " + host + ", port: " + port + ") -> start");
try {
while (true) {
face.processEvents();
// System.out.println("faceId: " + id + " -> processEvent");
Thread.sleep(1);
}
} catch (IOException | EncodingException | InterruptedException e) {
System.out.println(e.getMessage());
this.face = new Face(this.host, this.port);
if (this.statusCallback != null) {
this.statusCallback.onError(this);
}
}
}
interface StatusCallback {
void onError(ProcessEventTask task);
}
}
}
@@ -0,0 +1,93 @@
package cn.minoa.dataRequestInterface;
import net.named_data.jndn.Name;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.pib.Pib;
import net.named_data.jndn.security.pib.PibIdentity;
import net.named_data.jndn.security.pib.PibImpl;
import net.named_data.jndn.security.pib.PibSqlite3;
import net.named_data.jndn.security.tpm.Tpm;
import net.named_data.jndn.security.tpm.TpmBackEnd;
import net.named_data.jndn.security.tpm.TpmBackEndFile;
import net.named_data.jndn.security.v2.CertificateV2;
public enum KeyManager {
INSTANCE;
private KeyChain keyChain = null;
KeyManager() {
try {
this.keyChain = getOrBuildKeyChain("/default");
} catch (KeyChain.Error | PibImpl.Error | Pib.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error error) {
error.printStackTrace();
}
}
public KeyManager initKeyChain(String identityName) throws Pib.Error, Tpm.Error, TpmBackEnd.Error,
CertificateV2.Error, KeyChain.Error, PibImpl.Error {
this.keyChain = getOrBuildKeyChain(identityName);
return this;
}
public CertificateV2 getCertification(String identityName, String keyName) throws Pib.Error, PibImpl.Error,
CertificateV2.Error, Tpm.Error, KeyChain.Error, TpmBackEnd.Error {
return KeyManager.INSTANCE.initKeyChain(identityName)
.getKeyChain()
.getPib()
.getIdentity(new Name(identityName))
.getKey(new Name(keyName))
.getDefaultCertificate();
}
private KeyChain getOrBuildKeyChain(String identityName) throws
KeyChain.Error, PibImpl.Error, Pib.Error, Tpm.Error, TpmBackEnd.Error, CertificateV2.Error {
KeyChain keyChain = null;
PibSqlite3 pibSqlite3 = new PibSqlite3("./ndn/pid");
TpmBackEndFile tpmBackEndFile = new TpmBackEndFile("./ndn/tpm");
try {
keyChain = new KeyChain(pibSqlite3, tpmBackEndFile);
PibIdentity identity = keyChain.getPib().getIdentity(new Name(identityName));
keyChain.setDefaultIdentity(identity);
} catch (Pib.Error error) {
error.printStackTrace();
System.out.println(error.getMessage());
// 获取本地记录的用户的身份失败,可能是一个新的身份
PibIdentity identity = keyChain.createIdentityV2(new Name(identityName));
keyChain.setDefaultIdentity(identity);
pibSqlite3.setDefaultKeyOfIdentity(identity.getName(), identity.getDefaultKey().getName());
}
return keyChain;
}
// 判断本地是否有某个标识名对应的证书
public boolean isInKeyChain(String identityName) throws
KeyChain.Error, PibImpl.Error, Pib.Error, Tpm.Error, TpmBackEnd.Error, CertificateV2.Error {
KeyChain keyChain = null;
PibSqlite3 pibSqlite3 = new PibSqlite3("./ndn/pid");
TpmBackEndFile tpmBackEndFile = new TpmBackEndFile("./ndn/tpm");
try {
keyChain = new KeyChain(pibSqlite3, tpmBackEndFile);
PibIdentity identity = keyChain.getPib().getIdentity(new Name(identityName));
keyChain.setDefaultIdentity(identity);
return true;
} catch (Pib.Error error) {
// error.printStackTrace();
System.out.println(error.getMessage());
System.out.println("本地无该标识名称对应的证书:"+identityName);
return false;
}
}
public CertificateV2 getCertification(String identityName) throws Pib.Error, PibImpl.Error {
return keyChain.getPib().getIdentity(new Name(identityName)).getDefaultKey().getDefaultCertificate();
}
public KeyChain getKeyChain() {
return keyChain;
}
public void setKeyChain(KeyChain keyChain) {
this.keyChain = keyChain;
}
}
@@ -4,20 +4,24 @@ package cn.minoa.dataRequestInterface;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import cn.minoa.model.SingleNotice;
import cn.minoa.util.KeyStorageUtil;
import cn.minoa.util.StringByteLengthUtil;
import net.named_data.jndn.*;
import net.named_data.jndn.security.pib.Pib;
import net.named_data.jndn.security.pib.PibImpl;
import net.named_data.jndn.security.tpm.Tpm;
import net.named_data.jndn.security.tpm.TpmBackEnd;
import net.named_data.jndn.security.v2.CertificateV2;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import cn.minoa.MainApp;
import cn.minoa.model.SingleMessage;
import net.named_data.jndn.Data;
import net.named_data.jndn.Face;
import net.named_data.jndn.Interest;
import net.named_data.jndn.Name;
import net.named_data.jndn.OnData;
import net.named_data.jndn.encoding.EncodingException;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.SecurityException;
@@ -28,73 +32,118 @@ import net.named_data.jndn.security.tpm.TpmBackEndMemory;
import net.named_data.jndn.util.Blob;
public class MinoaDataAPI {
static private String keyChainNameString = "/wefree";
private String minoaServerIpString;
private Integer minoaServerPortInteger;
private String globalPrefixString;
private String pidDbPathString;
// private String minoaServerIpString = "121.15.171.89";
// private Integer minoaServerPortInteger=6363;
// private String globalPrefixString = "/ndn/edu/pkusz/OA";
public static String keyChainNameString = "/default";
public static String minoaServerIpString;
public static Integer minoaServerPortInteger;
public static String globalPrefixString;
// public static String pidDbPathString;
KeyChain keyChain;
Face face;
public DataCacheQueue dataCacheQueue;
// 同一兴趣包超时或丢包次数达到上限时的错误信息
public static String timeoutError = "timeout times reaches the upper limit.";
// 由于连接问题(多次超时/丢包),返回给主线程的错误码
public static Integer timeoutCodeInteger = 333;
// 同一兴趣包超时或丢包次数达到上限时的错误信息
public static String nackError = "receive nack.";
// 由于连接问题(多次超时/丢包),返回给主线程的错误码
public static Integer nackCodeInteger = 334;
// KeyChain keyChain;
public static Face face;
public volatile DataCacheQueue dataCacheQueue;
private MainApp mainApp;
// 标志连接是否正常
private boolean isConnected;
//发送的数据是否发送成功,key:第几个数据片,从0开始,value:该数据片超时次数
private Map<Long, Integer> timeOutNums = new ConcurrentHashMap<>();
// 超时重传上限数值,某个兴趣包的重传次数超过此数值,则放弃重传,直接返回false
private Integer timeoutCeil = 10;
public MinoaDataAPI(MainApp mainApp) {
// TODO Auto-generated constructor stub
minoaServerIpString=mainApp.minoaServerIpString;
minoaServerPortInteger=mainApp.minoaServerPortInteger;
globalPrefixString=mainApp.globalPrefixString;
this.face = new Face(minoaServerIpString,minoaServerPortInteger);
isConnected=false;
this.dataCacheQueue = new DataCacheQueue();
this.mainApp = mainApp;
pidDbPathString=mainApp.getClientPath()+ File.separator+"ndn";
System.out.println("pidDbPathString: "+pidDbPathString);
runFace();
// pidDbPathString=mainApp.getClientPath()+ File.separator+"ndn";
// System.out.println("pidDbPathString: "+pidDbPathString);
runFace(minoaServerIpString, minoaServerPortInteger);
// 首先按照"/default"初始化KeyChain
try {
// 密钥“黑盒”
PibSqlite3 pibSqlite3 = new PibSqlite3(pidDbPathString);
TpmBackEndMemory tpmBackEndMemory = new TpmBackEndMemory();
keyChain = new KeyChain(pibSqlite3, tpmBackEndMemory);
PibIdentity identity = keyChain.getPib().getIdentity(new Name(keyChainNameString));
keyChain.setDefaultIdentity(identity);
System.out.println(keyChain.getDefaultCertificateName().toUri());
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
KeyManager.INSTANCE.initKeyChain(keyChainNameString);
} catch (Pib.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
}
// 从本地初始化keyName
String keyString= KeyStorageUtil.getKeyName();
try {
// 如果本地keyName指向的证书确实在keyChain中,就将该证书取出
if((keyString!=null)&&(KeyManager.INSTANCE.isInKeyChain(keyString))){
keyChainNameString=keyString;
System.out.println("keyChainNameString: "+keyChainNameString);
// 再次按照本地证书前缀初始化KeyChain
try {
KeyManager.INSTANCE.initKeyChain(keyChainNameString);
} catch (Pib.Error | Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
}
}
} catch (Pib.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
}
}
/**
* 判断某个key对应的兴趣包的超时次数是否超过阈值
*
* @return
*/
private boolean isInterestTimeOut(Long timeoutMapKey) {
if (timeOutNums.get(timeoutMapKey) > timeoutCeil) {
return true;
}
return false;
}
// 开辟线程运行face
private void runFace() {
public boolean runFace(String ipString, Integer portInteger) {
if (isConnected) {
return true;
}
this.face = new Face(ipString, portInteger);
isConnected = true;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// System.out.println("face is trying to link...");
// TODO Auto-generated method stub
try {
while (true) {
face.processEvents();
// 线程暂时休眠
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thread.sleep(1);
}
} catch (IOException e) {
} catch (InterruptedException | EncodingException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (EncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// e.printStackTrace();
System.out.println(e.getMessage());
isConnected = false;
}
}
});
thread.start();
return isConnected;
}
public boolean runFace(String ipString) {
return this.runFace(ipString, minoaServerPortInteger);
}
public boolean runFace() {
return this.runFace(minoaServerIpString, minoaServerPortInteger);
}
// 开辟线程监听新消息/新通知/新审批
@@ -303,14 +352,6 @@ public class MinoaDataAPI {
singleMessage.setTime(timeLong);
singleMessage.setToName(mainApp.loginer.getUserName());
singleMessage.setMsgId(idInteger);
// 加入前端数据内存
// System.out.println("MinoaDataAPI-addNewMessage-singleMessageString: "+singleMessageString);
// System.out.println("MinoaDataAPI-addNewMessage-fromName: "+fromNameString);
// mainApp.messageLogMap.get(fromNameString).add(singleMessage);
// //加入未读消息的列表中
// mainApp.notReadMessageList.addNotReadMessage(singleMessage);
// // 产生消息气泡
// mainApp.newMessageBubble(singleMessage);
// 将这条新消息交给mainApp处理
mainApp.handleGetNewMessage(singleMessage);
System.out.println("MinoaDataAPI-handleGetNewMessage success: " + singleMessageString);
@@ -320,99 +361,6 @@ public class MinoaDataAPI {
}
}
// //判断是否有新消息产生=>废了,换接口了
// private boolean judgeNewMessageProdution() {
// //发送数据请求
// Long seqLong=mainApp.getNewDataReqId();
// OrderInfo orderInfo=new OrderInfo();
// orderInfo.setSeq(seqLong);
// orderInfo.setJsonString(getHasNewsJson());
// mainApp.minoaDataAPI.executeOrder("/hasNews", orderInfo);
// //获取回复消息
// ResponseData responseData=mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
// JSONObject jsonObject=responseData.praseRequestData();
//// System.out.println("hasNews-JSON: "+jsonObject.toString());
// Integer codeInteger = null;
// try {
// codeInteger = jsonObject.getInt("code");
// } catch (JSONException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// if(codeInteger==200) {
// String dataString;
// try {
// dataString = jsonObject.getString("data");
// JSONObject dataJSONObject=new JSONObject(dataString);
// Integer msgInteger=dataJSONObject.getInt("msg");
// if(msgInteger>0) {
// System.out.println(msgInteger);
// return true;
// }
// } catch (JSONException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// return false;
// }
//
// //获取是否有新消息产生的json字符串
// private String getHasNewsJson() {
// JSONObject jsonObject =new JSONObject();
// String commandString="/hasNews";
// String userNameString=mainApp.loginer.getUserName();
// String uuidString=mainApp.loginer.getUuid();
// try {
// jsonObject.put("command", commandString);
// jsonObject.put("username", userNameString);
// jsonObject.put("uuid", uuidString);
// } catch (Exception e) {
// // TODO: handle exception
// System.out.println("exception: " + e.getMessage());
// }
// return jsonObject.toString();
// }
// 获取注册请求字符串
// static private String getRegisterJson() {
// JSONObject jsonObject = new JSONObject();
// String mPubKey = "Bv0CsQcuCAR3Z2gwCANLRVkICH9+4yjVUHZaCAxjZXJ0LXJlcXVlc3QICf0AAAFv\nEUSBehQJGAECGQQANu6AFf0BJjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBANbFutCAZqFjHEa16tYvy4lBgi9/zixKWQzE9I72vaG2Imym+6KR30qkAQOK\nh0uE5RD2YsGhRK99rde+JOqIfk2/sunhp4nctOS5f4DeuOty58ekrO+Co9ZFmNBI\nmyk5i/hakjBEd/vdD7b1VadDRep5mWs3rgCinZOUfVaZ4oKqSws7ZWMvOSlRMOOi\nVzj53P4poY109S6aWmi3xKw/D76vfJapjdOB9Dg7S3rz0Rve1F/ajHCXWLt4XU3k\nUCiBn3Qmt6UD/MyDBaaUCfOvHTN6yVPtN6aOtYJVBAWt/P1ahLYhWkSm6KvrwMt0\nRzy2lw/lPriT99REItc/0wK6XwkCAwEAARZGGwEBHBcHFQgEd2doMAgDS0VZCAh/\nfuMo1VB2Wv0A/Sb9AP4PMjAxOTEyMTdUMDAzMTQw/QD/DzIwMTkxMjI3VDAwMzEz\nORf9AQCM+8WROXfi8WD9DydfLuSUxV0v3KW/Gn422/puDrkwwi1R2ogsAUc2O8pp\npuMLjWrQOTgE6ZTg80uWoDSUjjk44aMjkL2SAfp62vHRbGFx7+dckHAtF+DS6NH7\nX2vojFHOg6fksOE1M7XqLHmEEctZrFVSnQO7nB3DfRg+BqzZC/iy+8YAvTIvqA1c\nNsKYkmNITB80aM1v2H7fKnV4ZJpZnW71G5vbaPUseeklalQ2vEuBgWdd/1PL/0Ml\nI52npzqoeKAEpLp+vBwGN5ryGtWKB12nNimpMfevQAn/9BVIg59lZ7DIlE0sWmgW\nnwDxIXKebdViOejHlKwNAykxRRWw";
// String commandString = "/register";
// String userNameString = "oa_wefree";
// String passWordString = "12345678";
// String phoneString = "10000000006";
// Integer levelInteger = 0;
// try {
// jsonObject.put("command", commandString);
// jsonObject.put("username", userNameString);
// jsonObject.put("password", passWordString);
// jsonObject.put("phone", phoneString);
// jsonObject.put("publicKey", mPubKey);
// jsonObject.put("level", levelInteger);
// } catch (Exception e) {
// System.out.println("exception: " + e.getMessage());
// }
// return jsonObject.toString();
// }
// //"获取最近三天未读实时消息"
// static private String getGetRTMsgJson() {
// JSONObject jsonObject =new JSONObject();
// String commandString="/getRTMsg";
// String userNameString="oa_wefree";
// String uuidString="29c8f0a4-52d7-4478-90f0-6136996dbe96";
// try {
// jsonObject.put("command", commandString);
// jsonObject.put("username", userNameString);
// jsonObject.put("uuid", uuidString);
// } catch (Exception e) {
// // TODO: handle exception
// System.out.println("exception: " + e.getMessage());
// }
// return jsonObject.toString();
// }
// 根据命令前缀获取相应的请求字符串【JSON】
static private String getRequestStr(String orderPrefix, OrderInfo orderInfo) {
String requestStr;
@@ -475,77 +423,6 @@ public class MinoaDataAPI {
return requestStr;
}
// 执行文件下载的特殊数据请求语句
// 执行数据请求语句
public boolean executeOrder(String orderPrefix, OrderInfo orderInfo, String localDir, String localName) {
// 获取json格式的数据请求字符串
String requestStr = getRequestStr(orderPrefix, orderInfo);
// System.out.println("requestStr: "+requestStr);
// 命令前缀格式不对的情况下返回false
if (requestStr.equals("*wrong command string*")) {
System.out.println(requestStr);
return false;
}
// 发送数据兴趣包
Name name = new Name(globalPrefixString + orderPrefix + "/" + orderInfo.getSeq());
Interest interest = new Interest(name);
interest.setMustBeFresh(true);
try {
// 文件下载
interest.setApplicationParameters(new Blob(requestStr));
// 密钥“黑盒”
keyChain.sign(interest);
this.expressTheDownloadInterest(orderPrefix, interest, orderInfo,localDir,localName);
return true;
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
return false;
}
}
// 执行数据请求语句
public boolean executeOrder(String orderPrefix, OrderInfo orderInfo,String serverpath) {
// 获取json格式的数据请求字符串
String requestStr = getRequestStr(orderPrefix, orderInfo);
// System.out.println("requestStr: "+requestStr);
// 命令前缀格式不对的情况下返回false
if (requestStr.equals("*wrong command string*")) {
System.out.println(requestStr);
return false;
}
// 发送数据兴趣包
Name name = new Name(globalPrefixString + orderPrefix + "/" + orderInfo.getSeq());
Interest interest = new Interest(name);
interest.setMustBeFresh(true);
// System.out.println("interest name: "+name.toString());
try {
if (orderPrefix.equals("/downloadFile")) {
// 文件下载
interest.setApplicationParameters(new Blob(requestStr));
// 密钥“黑盒”
keyChain.sign(interest);
this.expressTheDownloadInterest(orderPrefix, interest, orderInfo);
} else if (orderPrefix.equals("/uploadFile")) {
// 文件上传[interest和keyChain的参数设置在函数体内]
this.expressTheUploadInterest(orderPrefix, interest, orderInfo,serverpath);
}else {
interest.setApplicationParameters(new Blob(requestStr));
// System.out.println("setApplicationParameters-blob: "+requestStr);
// 密钥“黑盒”
keyChain.sign(interest);
// System.out.println(interest.toUri());
this.expressTheInterest(orderPrefix, interest, orderInfo.getSeq());
}
return true;
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
return false;
}
}
// 执行数据请求语句
public boolean executeOrder(String orderPrefix, OrderInfo orderInfo) {
// 获取json格式的数据请求字符串
@@ -561,322 +438,28 @@ public class MinoaDataAPI {
Name name = new Name(globalPrefixString + orderPrefix + "/" + orderInfo.getSeq());
Interest interest = new Interest(name);
interest.setMustBeFresh(true);
// System.out.println("interest name: "+name.toString());
interest.setApplicationParameters(new Blob(requestStr));
interest.setInterestLifetimeMilliseconds(2000);
try {
if (orderPrefix.equals("/downloadFile")) {
// 文件下载
interest.setApplicationParameters(new Blob(requestStr));
// 密钥“黑盒”
keyChain.sign(interest);
this.expressTheDownloadInterest(orderPrefix, interest, orderInfo);
} else if (orderPrefix.equals("/uploadFile")) {
// 文件上传[interest和keyChain的参数设置在函数体内]
this.expressTheUploadInterest(orderPrefix, interest, orderInfo,"/");
}else {
interest.setApplicationParameters(new Blob(requestStr));
// System.out.println("setApplicationParameters-blob: "+requestStr);
// 密钥“黑盒”
keyChain.sign(interest);
// System.out.println(interest.toUri());
this.expressTheInterest(orderPrefix, interest, orderInfo.getSeq());
}
// keyChain.sign(interest);
// 使用KeyManager管理兴趣包签名
KeyManager.INSTANCE.getKeyChain().sign(interest);
this.expressTheInterest(orderPrefix, interest, orderInfo.getSeq());
return true;
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
return false;
}
}
//文件上传到指定服务器路径下
private void expressTheUploadInterest(String orderPrefix, Interest interest, OrderInfo orderInfo,String serverpath) {
// 设置回执前缀
ResponseData responseData = new ResponseData();
responseData.setPrefix(orderPrefix);
byte[] requestByte = null; // 请求数据
// 重写ondata
try {
// 解析并修改文件名【window转server】
String localFilePath = "";
String serverFilePath = "";
Integer offsetInteger = 0;
try {
// 解析
JSONObject jsonObject = new JSONObject(orderInfo.getJsonString());
offsetInteger = jsonObject.getInt("offset");
localFilePath = jsonObject.getString("filename");
serverFilePath = serverpath + getPureFileNameFromWindows(localFilePath);
// 修改
jsonObject.remove("filename");
jsonObject.put("filename", serverFilePath);
orderInfo.setJsonString(jsonObject.toString());
System.out.println("request head str: " + orderInfo.getJsonString());
System.out.println("head str length: "+orderInfo.getJsonString().length());
System.out.println("head str byte length: "+ StringByteLengthUtil.getByteLength(orderInfo.getJsonString()));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 从本地读取数据
byte[] content = new byte[10000]; // 文件分片内容
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(localFilePath, "rw");
// 设置文件的读取起点
randomAccessFile.seek(offsetInteger);
// 尝试读取数据
int readLen = randomAccessFile.read(content, 0, 7000);
randomAccessFile.close();
System.out.println("file slice readLen == " + readLen);
// int jsonLen = orderInfo.getJsonString().length();
int jsonLen=StringByteLengthUtil.getByteLength(orderInfo.getJsonString());
requestByte = new byte[jsonLen + 1 + readLen];
System.arraycopy(orderInfo.getJsonString().getBytes("utf-8"), 0, requestByte, 0, jsonLen);
requestByte[jsonLen] = 0;
System.arraycopy(content, 0, requestByte, jsonLen + 1, readLen);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 赋值兴趣包的附带信息,并标志区块链
System.out.println("requestByte-len: " + requestByte.length);
System.out.println("requestByte: " + requestByte);
interest.setApplicationParameters(new Blob(requestByte));
System.out.println("interest.getApplicationParameters().size(): "+interest.getApplicationParameters().size());
// 密钥“黑盒”
try {
keyChain.sign(interest);
} catch (Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyChain.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (net.named_data.jndn.security.tpm.TpmBackEnd.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 使用匿名内部类,发送数据请求兴趣包
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
// 返回成功写入或失败写入消息
responseData.setResponseData(data.getContent().toString());
dataCacheQueue.setResponseData(orderInfo.getSeq(), responseData);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
//文件上传=>默认上传到根目录;此函数应废弃不予使用
// private void expressTheUploadInterest(String orderPrefix, Interest interest, OrderInfo orderInfo) {
// // 设置回执前缀
// ResponseData responseData = new ResponseData();
// responseData.setPrefix(orderPrefix);
// byte[] requestByte = null; // 请求数据
// // 重写ondata
// try {
// // 解析并修改文件名【window转server】
// String localFilePath = "";
// String serverFilePath = "";
// Integer offsetInteger = 0;
// try {
// // 解析
// JSONObject jsonObject = new JSONObject(orderInfo.getJsonString());
// offsetInteger = jsonObject.getInt("offset");
// localFilePath = jsonObject.getString("filename");
// serverFilePath = mainApp.fileServerBinPath + getPureFileNameFromWindows(localFilePath);
// // 修改
// jsonObject.remove("filename");
// jsonObject.put("filename", serverFilePath);
// orderInfo.setJsonString(jsonObject.toString());
// System.out.println("request head str: " + orderInfo.getJsonString());
// } catch (JSONException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// // 从本地读取数据
// byte[] content = new byte[10000]; // 文件分片内容
// try {
// RandomAccessFile randomAccessFile = new RandomAccessFile(localFilePath, "rw");
// // 设置文件的读取起点
// randomAccessFile.seek(offsetInteger);
// // 尝试读取数据
// int readLen = randomAccessFile.read(content, 0, 7000);
// randomAccessFile.close();
// System.out.println("file slice readLen == " + readLen);
// int jsonLen = StringByteLengthUtil.getByteLength(orderInfo.getJsonString());
// requestByte = new byte[jsonLen + 1 + readLen];
// System.arraycopy(orderInfo.getJsonString().getBytes("utf-8"), 0, requestByte, 0, jsonLen);
// requestByte[jsonLen] = 0;
// System.arraycopy(content, 0, requestByte, jsonLen + 1, readLen);
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// // 赋值兴趣包的附带信息,并标志区块链
// System.out.println("requestByte-len: " + requestByte.length);
// System.out.println("requestByte: " + requestByte);
// interest.setApplicationParameters(new Blob(requestByte));
// // 密钥“黑盒”
// try {
// keyChain.sign(interest);
// } catch (Error e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (KeyChain.Error e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (net.named_data.jndn.security.tpm.TpmBackEnd.Error e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (SecurityException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// // 使用匿名内部类,发送数据请求兴趣包
// face.expressInterest(interest, new OnData() {
// @Override
// public void onData(Interest interest, Data data) {
// // 返回成功写入或失败写入消息
// responseData.setResponseData(data.getContent().toString());
// dataCacheQueue.setResponseData(orderInfo.getSeq(), responseData);
// }
// });
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// // 合并两个Byte[]
// public byte[] byteMerger(byte[] bt1, byte[] bt2) {
// byte[] bt3 = new byte[bt1.length + bt2.length];
// System.arraycopy(bt1, 0, bt3, 0, bt1.length);
// System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
// return bt3;
// }
//下载文件的数据分片到指定路径,并将文件重命名为指定文件名
private void expressTheDownloadInterest(String orderPrefix, Interest interest, OrderInfo orderInfo,String localDir,String localName) {
// 设置回执前缀
ResponseData responseData = new ResponseData();
responseData.setPrefix(orderPrefix);
try {
// 使用匿名内部类,发送数据请求兴趣包
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
// 解析文件名、分片编号
String filePathString = localDir;
Integer sliceSizeInteger = mainApp.sliceSize;
String filenameString = localName;
Integer sliceNoInteger = null;
try {
JSONObject jsonObject = new JSONObject(orderInfo.getJsonString());
sliceNoInteger = jsonObject.getInt("sliceNo");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 写入本地文件
Integer successInfoInteger = 1;
try {
System.out.println("开始写入文件数据分片... :" + filePathString + filenameString);
RandomAccessFile randomAccessFile = new RandomAccessFile(filePathString + filenameString, "rw");
int contentSize = data.getContent().size();
System.out.println("该数据分片长度为:" + contentSize);
byte[] content = new byte[contentSize];
for (int i = 0; i < contentSize; i++) {
content[i] = data.getContent().buf().get(i);
}
// 设置数据分片写入到文件的起点位置
randomAccessFile.seek(sliceNoInteger * sliceSizeInteger);
// 写入数据分片
randomAccessFile.write(content, 0, contentSize);
randomAccessFile.close();
System.out.println("写入文件数据分片完毕:" + filePathString + filenameString);
successInfoInteger = 0;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 返回成功写入或失败写入消息
responseData.setResponseData(successInfoInteger.toString());
dataCacheQueue.setResponseData(orderInfo.getSeq(), responseData);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//下载文件的数据分片到默认路径
private void expressTheDownloadInterest(String orderPrefix, Interest interest, OrderInfo orderInfo) {
// 设置回执前缀
ResponseData responseData = new ResponseData();
responseData.setPrefix(orderPrefix);
try {
// 使用匿名内部类,发送数据请求兴趣包
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
// 解析文件名、分片编号
String filePathString = mainApp.fileLocalPath;
Integer sliceSizeInteger = mainApp.sliceSize;
String filenameString = null;
Integer sliceNoInteger = null;
try {
JSONObject jsonObject = new JSONObject(orderInfo.getJsonString());
filenameString = getPureFileName(jsonObject.getString("filename"));
sliceNoInteger = jsonObject.getInt("sliceNo");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 写入本地文件
Integer successInfoInteger = 1;
try {
System.out.println("开始写入文件数据分片... :" + filePathString + filenameString);
RandomAccessFile randomAccessFile = new RandomAccessFile(filePathString + filenameString, "rw");
int contentSize = data.getContent().size();
System.out.println("该数据分片长度为:" + contentSize);
byte[] content = new byte[contentSize];
for (int i = 0; i < contentSize; i++) {
content[i] = data.getContent().buf().get(i);
}
// 设置数据分片写入到文件的起点位置
randomAccessFile.seek(sliceNoInteger * sliceSizeInteger);
// 写入数据分片
randomAccessFile.write(content, 0, contentSize);
randomAccessFile.close();
System.out.println("写入文件数据分片完毕:" + filePathString + filenameString);
successInfoInteger = 0;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 返回成功写入或失败写入消息
responseData.setResponseData(successInfoInteger.toString());
dataCacheQueue.setResponseData(orderInfo.getSeq(), responseData);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void expressTheInterest(String orderPrefix, Interest interest, Long dataReqId) {
ResponseData responseData = new ResponseData();
responseData.setPrefix(orderPrefix);
HandleInterestTimeOutAndNack handleInterestTimeOutAndNack =
new HandleInterestTimeOutAndNack(orderPrefix, interest, dataReqId);
try {
// 使用匿名内部类,发送数据请求兴趣包
if(orderPrefix.equals("/getDataSlice")) {
if (orderPrefix.equals("/getDataSlice")) {
//接收数据块
face.expressInterest(interest, new OnData() {
@Override
@@ -886,15 +469,19 @@ public class MinoaDataAPI {
byte[] content = new byte[contentSize];
for (int i = 0; i < contentSize; i++) {
content[i] = data.getContent().buf().get(i);
System.out.print(i+": "+content[i]+" ");
System.out.print(i + ": " + content[i] + " ");
}
System.out.println("");
System.out.println("notice content: "+content);
System.out.println("notice content: " + content);
responseData.setFileSlice(content);
dataCacheQueue.setResponseData(dataReqId, responseData);
// 重置其超时次数记录
if (timeOutNums.containsKey(dataReqId)) {
timeOutNums.remove(dataReqId);
}
}
});
}else {
}, handleInterestTimeOutAndNack, handleInterestTimeOutAndNack);
} else {
face.expressInterest(interest, new OnData() {
@Override
public void onData(Interest interest, Data data) {
@@ -904,8 +491,12 @@ public class MinoaDataAPI {
// System.out.println("ondata data: "+data.getContent().toString());
responseData.setResponseData(data.getContent().toString());
dataCacheQueue.setResponseData(dataReqId, responseData);
// 重置其超时次数记录
if (timeOutNums.containsKey(dataReqId)) {
timeOutNums.remove(dataReqId);
}
}
});
}, handleInterestTimeOutAndNack, handleInterestTimeOutAndNack);
}
} catch (IOException e) {
// TODO Auto-generated catch block
@@ -913,15 +504,8 @@ public class MinoaDataAPI {
}
}
// 写头像
// public Integer writeHeadPhotoIntoLocalFile(String filenameString,
// Integer sliceNo,Integer sliceSize,byte[] bytes) {
// String pathString=mainApp.fileLocalPath;
// return writeIntoLocalFile(pathString, filenameString, sliceNo, sliceSize, bytes);
// }
// 根据包含路径的文件名获取纯文件名[linux下]
public String getPureFileName(String pathfilename) {
public static String getPureFileName(String pathfilename) {
// 标记最后一个/的下标
int indexLeft = -1;
for (int i = 0; i < pathfilename.length(); i++) {
@@ -939,7 +523,7 @@ public class MinoaDataAPI {
}
// 根据包含路径的文件名获取纯文件名[windows本地]
public String getPureFileNameFromWindows(String pathfilename) {
public static String getPureFileNameFromWindows(String pathfilename) {
// 标记最后一个/的下标
int indexLeft = -1;
for (int i = 0; i < pathfilename.length(); i++) {
@@ -955,21 +539,91 @@ public class MinoaDataAPI {
return pathfilename.substring(indexLeft + 1, pathfilename.length());
}
}
// // 向指定本地文件写入指定数据分片=》被ondata调用
// public Integer writeIntoLocalFile(String pathString,String filenameString,
// Integer sliceNo,Integer sliceSize,byte[] bytes) {
// try {
// @SuppressWarnings("resource")
// RandomAccessFile randomAccessFile=new RandomAccessFile(pathString+filenameString, "rw");
// int contentSize=
// randomAccessFile.write(bytes,sliceNo*sliceSize,bytes.length);
// return 0;
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// return 1;
// }
// }
// 解决处理兴趣包超时之后的重传问题[除上传下载外的兴趣包]
public class HandleInterestTimeOutAndNack implements OnTimeout, OnNetworkNack {
// 命令前缀
private String orderPrefix;
// 兴趣包
private Interest interest;
// 请求序列号
private Long dataReqId;
// 标记是否拿到网络回复(数据信息/超时信息):测试使用
public boolean isFinished = false;
public HandleInterestTimeOutAndNack(String orderPrefix, Interest interest, Long dataReqId) {
this.orderPrefix = orderPrefix;
this.interest = interest;
this.interest.setInterestLifetimeMilliseconds(2000);
this.dataReqId = dataReqId;
}
// 处理兴趣包超时
@Override
public void onTimeout(Interest interest) {
// 打印超时信息
System.out.println("########## Time out for interest " + interest.getName() + "###########");
// 记录此次丢包/超时
if (timeOutNums.containsKey(this.dataReqId)) {
int value = timeOutNums.get(this.dataReqId) + 1;
timeOutNums.put(this.dataReqId, value);
} else {
timeOutNums.put(this.dataReqId, 1);
}
// 根据是否多次超时,决定是否重传该兴趣包:暂时是全部重传
// 后期可以改作,超时次数超过阈值时候,
// 自拟定一个指定值放入数据回复缓存区,前端控制类收到该值,就
// 判定网络极其拥塞,进行弹窗提示。
if (!isInterestTimeOut(this.dataReqId)) {
// 超时次数没有超过阈值:重传该兴趣包
expressTheInterest(this.orderPrefix, this.interest, this.dataReqId);
} else {
// 超时次数超过阈值
System.out.println("该兴趣包的超时次数超过阈值:" + timeoutCeil + "!!!");
// 返回一个timeout信息放入datacache
ResponseData responseData = new ResponseData();
responseData.setPrefix(this.orderPrefix);
responseData.setResponseData(getWrongAnswerJson(timeoutCodeInteger, timeoutError));
dataCacheQueue.setResponseData(this.dataReqId, responseData);
}
// 打印重传信息
System.out.println("########## Resend the interest " + interest.getName() + "###########");
// 处理完成
isFinished = true;
}
// 处理收到一个Nack包
@Override
public void onNetworkNack(Interest interest, NetworkNack networkNack) {
// 打印超时信息
System.out.println("########## Nack for interest " + interest.getName()
+ ", Nack: " + networkNack.toString());
// 返回一个nack信息放入datacache
ResponseData responseData = new ResponseData();
responseData.setPrefix(this.orderPrefix);
responseData.setResponseData(getWrongAnswerJson(nackCodeInteger, nackError));
dataCacheQueue.setResponseData(this.dataReqId,responseData);
isFinished = true;
}
}
// 构造一个json,给前端返回一个可以进行JSON解析的错误信息
// 用以避免界面卡死
public static String getWrongAnswerJson(Integer wrongAnswerCode, String wrongAnswerString) {
JSONObject jsonObject = new JSONObject();
Integer code = wrongAnswerCode;
String errMsg = wrongAnswerString;
String data = "";
try {
jsonObject.put("code", code);
jsonObject.put("errMsg", errMsg);
jsonObject.put("data", data);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
// 关闭数据连接
public void closeDataConn() {
@@ -1,5 +1,6 @@
package cn.minoa.dataRequestInterface;
import cn.minoa.MainApp;
import org.json.JSONObject;
//请求数据时的附加请求信息
@@ -19,6 +20,17 @@ public class OrderInfo {
public void setSeq(Long seqLong) {
this.seqLong=seqLong;
// 查看是否连接正常,否,重新尝试连接;
// 重新连接失败,默认是ip有问题,返回一个错误包
if(!MainApp.isFaceLinked()){
System.out.println("!!!face link error!!!");
ResponseData responseData=new ResponseData();
String wrongAnswer=MinoaDataAPI.getWrongAnswerJson(336,
"face link error");
responseData.setPrefix("/wrongAnswer");
responseData.setResponseData(wrongAnswer);
MainApp.minoaDataAPI.dataCacheQueue.setResponseData(seqLong,responseData);
}
}
public Long getSeq() {
@@ -0,0 +1,396 @@
package cn.minoa.dataRequestInterface;
import cn.minoa.MainApp;
import cn.minoa.util.StringByteLengthUtil;
import net.named_data.jndn.*;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.SecurityException;
import net.named_data.jndn.security.pib.PibImpl;
import net.named_data.jndn.util.Blob;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author mac
* @description
* @date 2020-03-22 18:28
*/
public class UpLoadClientBasedFacePool {
private String orderPrefix = "/uploadFile";
private String serverPath;
private File file;
//总数据片大小
private Long sliceNumbers;
private Long currentOffset = 0L;
private CongestionWindow congestionWindow = new CongestionWindow();
private FacePool facePool;
// 要上传的本地文件对象
private RandomAccessFile randomAccessFile;
//发送失败,需要重新发送的数据。key:第几个数据片,从0开始计数,value:文件偏移
// private Map<Long, Long> failedSlice = new ConcurrentHashMap<>();
//存放发送失败数据的文件偏移
private ConcurrentLinkedQueue<Long> failedSlice = new ConcurrentLinkedQueue<>();
//发送的数据是否发送成功,key:第几个数据片,从0开始,value:是否发送成功
private Map<Long, Boolean> sendRes = new ConcurrentHashMap<>();
//收到回复的数量
public AtomicLong recvCount = new AtomicLong(0);
//发送的数据是否发送成功,key:第几个数据片,从0开始,value:该数据片超时次数
private Map<Long, Integer> timeOutNums = new ConcurrentHashMap<>();
// 超时重传上限数值,某个兴趣包的重传次数超过此数值,则放弃重传,直接返回false
private Integer timeoutCeil=15;
public UpLoadClientBasedFacePool(File file, String serverPath, Integer facepoolnumber){
this.file = file;
this.serverPath = serverPath;
this.facePool=new FacePool(facepoolnumber);
this.facePool.start(MinoaDataAPI.minoaServerIpString, MinoaDataAPI.minoaServerPortInteger);
System.out.println("***********FacePool中并发数:"+facepoolnumber+"***********");
}
/**
* 判断是否含有超时次数超过阈值的
* @return
*/
private boolean isTimeOut(){
for (Map.Entry<Long, Integer> entry : timeOutNums.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
if(entry.getValue() > timeoutCeil){
return true;
}
}
return false;
}
/**
* 上传数据的主函数
* @return
*/
public boolean uploadData(){
// 先初始化一个本地文件
try {
this.randomAccessFile = new RandomAccessFile(this.file.getAbsolutePath(), "rw");
System.out.println("本地文件打开");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(file.length()% MainApp.sliceSize == 0){
sliceNumbers = file.length()/ MainApp.sliceSize;
}else{
sliceNumbers = file.length()/ MainApp.sliceSize + 1;
}
while(true){
//判断是否已经上传安成
if(sliceNumbers <= recvCount.longValue()){
break;
}
// 判断是否已经被用户终止上传
if(MainApp.isCancelFileTransferFlag){
System.out.println("用户已主动中断上传");
try {
this.randomAccessFile.close();
System.out.println("本地文件关闭");
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
//每一次发送数据
int cwnd = 0;
//获取此次可以发送数据的个数
while((cwnd = congestionWindow.getAvailableCwnd()) <= 0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0; i<cwnd; i++){
//TODO 首先发送failedmap中的数据
if(failedSlice.size() > 0){
//首先发送failedslice中的数据
Long failOffset = failedSlice.poll();
System.out.println("发送数据, name: " + file.getName() +"offset" + currentOffset + ", failedSlice:" + failedSlice.size() );
sendData(failOffset);
}else{
if(currentOffset < file.length()){
System.out.println("发送数据, name: " + file.getName() +"offset" + currentOffset + ", failedSlice:" + failedSlice.size() );
sendData(currentOffset);
currentOffset += MainApp.sliceSize;
}
}
congestionWindow.inFlightIncrease();
congestionWindow.nOutInterestIncrease();
}
if(isTimeOut()){
System.out.println("丢包超过阈值: "+timeoutCeil+" ,文件传输主动中断");
this.facePool.shutdownNow();
try {
this.randomAccessFile.close();
System.out.println("本地文件关闭");
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
try {
this.randomAccessFile.close();
System.out.println("本地文件关闭");
} catch (IOException e) {
e.printStackTrace();
}
this.facePool.shutdownNow();
return true;
}
/**
* 发送一个数据片
* @param offset
*/
private void sendData(Long offset){
facePool.submit(freeface -> {
OrderInfo orderInfo = new OrderInfo();
Long seqLong = MainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
String testStr = DownAndUpLoadData.getUploadFile(file.getAbsolutePath(), offset);
//System.out.println("*******************:" + testStr + "*******************");
orderInfo.setJsonString(testStr);
// 获取json格式的数据请求字符串
//String requestStr = MinoaDataAPI.getRequestStr(orderPrefix, orderInfo);
// 发送数据兴趣包
Name name = new Name(MinoaDataAPI.globalPrefixString + orderPrefix + "/" + seqLong);
Interest interest = new Interest(name);
interest.setMustBeFresh(true);
try {
ResponseData responseData = new ResponseData();
responseData.setPrefix(orderPrefix);
byte[] requestByte = null; // 请求数据
// 重写ondata
try {
// 解析并修改文件名【window转server】
String localFilePath = "";
String serverFilePath = "";
try {
// 解析
JSONObject jsonObject = new JSONObject(orderInfo.getJsonString());
localFilePath = jsonObject.getString("filename");
// serverFilePath = serverpath + getPureFileNameFromWindows(localFilePath);
serverFilePath = serverPath + MinoaDataAPI.getPureFileNameFromWindows(localFilePath);
// 修改
jsonObject.remove("filename");
jsonObject.put("filename", serverFilePath);
orderInfo.setJsonString(jsonObject.toString());
System.out.println("request head str: " + orderInfo.getJsonString());
System.out.println("head str length: " + orderInfo.getJsonString().length());
System.out.println("head str byte length: " + StringByteLengthUtil.getByteLength(orderInfo.getJsonString()));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 从本地读取数据
byte[] content = new byte[10000]; // 文件分片内容
try {
synchronized (randomAccessFile) {
// RandomAccessFile randomAccessFile = new RandomAccessFile(localFilePath, "rw");
// 设置文件的读取起点
randomAccessFile.seek(offset);
// 尝试读取数据
int readLen = randomAccessFile.read(content, 0, 7000);
int jsonLen = StringByteLengthUtil.getByteLength(orderInfo.getJsonString());
requestByte = new byte[jsonLen + 1 + readLen];
System.arraycopy(orderInfo.getJsonString().getBytes("utf-8"), 0, requestByte, 0, jsonLen);
requestByte[jsonLen] = 0;
System.arraycopy(content, 0, requestByte, jsonLen + 1, readLen);
// randomAccessFile.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 赋值兴趣包的附带信息,并标志区块链
interest.setApplicationParameters(new Blob(requestByte));
//超时
interest.setInterestLifetimeMilliseconds(5000);
// 密钥“黑盒”
try {
// MinoaDataAPI.keyChain.sign(interest);
KeyManager.INSTANCE.getKeyChain().sign(interest);
} catch (PibImpl.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyChain.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (net.named_data.jndn.security.tpm.TpmBackEnd.Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
UpLoadData upLoadData = new UpLoadData(orderInfo.getSeq(), responseData, offset / MainApp.sliceSize);
UpLoadTimeout upLoadTimeout = new UpLoadTimeout(upLoadData);
UpLoadOnNetWorkNack upLoadOnNetWorkNack = new UpLoadOnNetWorkNack(upLoadData);
// 使用tcp发送数据请求兴趣包
// MinoaDataAPI.runFace();
freeface.expressInterest(interest, upLoadData, upLoadTimeout, upLoadOnNetWorkNack);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
e.printStackTrace();
}
});
}
public class UpLoadData implements OnData {
private Long seq;
private ResponseData responseData;
//第几个数据片
public Long sliceNum;
public boolean isFinished = false;
public UpLoadData(Long seq, ResponseData responseData, Long sliceNum){
this.seq = seq;
this.responseData = responseData;
this.sliceNum = sliceNum;
}
@Override
public void onData(Interest interest, Data data){
responseData.setResponseData(data.getContent().toString());
JSONObject jsonObject = responseData.praseRequestData();
congestionWindow.inFlightDecrease();
// 解析数据,是否成功上传
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (codeInteger == 200) {
recvCount.incrementAndGet();
congestionWindow.cwndIncrease();
System.out.println("" + sliceNum + "片上传成功!");
}else{
failedSlice.add(sliceNum* MainApp.sliceSize);
System.out.println("" + sliceNum + "片上传失败!");
}
//拥塞标记返回值,无意义,大于0就表示拥塞,直接进行窗口减小操作即可
if(data.getCongestionMark() > 0){
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&网络拥塞,滑动窗口减小,getCongestionMark" + data.getCongestionMark());
congestionWindow.cwndDecrease();
}else{
//如果没有检测到拥塞,则增加窗口
congestionWindow.nIndataIncrease();
}
if(timeOutNums.containsKey(sliceNum)){
timeOutNums.remove(sliceNum);
}
isFinished = true;
}
public int callbackCount = 0 ;
}
public class UpLoadTimeout implements OnTimeout {
private UpLoadData upLoadData;
public int callbackCount = 0 ;
public UpLoadTimeout(UpLoadData upLoadData) {
this.upLoadData = upLoadData;
}
@Override
public void onTimeout(Interest interest){
congestionWindow.inFlightDecrease();
failedSlice.add(upLoadData.sliceNum* MainApp.sliceSize);
callbackCount ++ ;
System.out.println("Time out for interest " + interest.getName());
upLoadData.isFinished = false;
//
if(timeOutNums.containsKey(upLoadData.sliceNum)){
int value = timeOutNums.get(upLoadData.sliceNum) + 1;
timeOutNums.put(upLoadData.sliceNum,value);
}else{
timeOutNums.put(upLoadData.sliceNum,1);
}
}
}
public class UpLoadOnNetWorkNack implements OnNetworkNack {
private UpLoadData upLoadData;
public int callbackCount = 0 ;
public UpLoadOnNetWorkNack(UpLoadData upLoadData) {
this.upLoadData = upLoadData;
}
@Override
public void onNetworkNack(Interest var1, NetworkNack var2){
congestionWindow.inFlightDecrease();
failedSlice.add(upLoadData.sliceNum* MainApp.sliceSize);
//
if(timeOutNums.containsKey(upLoadData.sliceNum)){
int value = timeOutNums.get(upLoadData.sliceNum) + 1;
timeOutNums.put(upLoadData.sliceNum,value);
}else{
timeOutNums.put(upLoadData.sliceNum,1);
}
callbackCount ++ ;
System.out.println("onNetworkNack " + var1.getName());
upLoadData.isFinished = true;
}
}
}
@@ -1,36 +0,0 @@
package cn.minoa.dataRequestInterface;
import net.named_data.jndn.*;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.pib.PibIdentity;
import net.named_data.jndn.security.pib.PibSqlite3;
import net.named_data.jndn.security.tpm.TpmBackEndMemory;
//import net.named_data.jndn.util.Blob;
//import org.json.JSONObject;
//生成密钥
public class creatNDNKey {
static private String pidDbPathString="";
// static private String pidDbPathString="E:\\MyCode\\newEclipseWorkspace\\minoa_client_windows_JavaFX11";
static private String keyChainNameString="/wefree";
static private String pidIdentityString="wefree";
public static void main(String args[]){
KeyChain keyChain ;
try{
//密钥“黑盒”
PibSqlite3 pibSqlite3 = new PibSqlite3(pidDbPathString);
TpmBackEndMemory tpmBackEndMemory = new TpmBackEndMemory() ;
keyChain = new KeyChain(pibSqlite3,tpmBackEndMemory ) ;
keyChain.createIdentityV2(new Name(keyChainNameString)) ;
PibIdentity identity = keyChain.getPib().getIdentity(new Name(pidIdentityString)); ;
keyChain.setDefaultIdentity(identity);
//输出测试
System.out.println(keyChain.getDefaultCertificateName().toUri());
System.out.println(keyChain.getPib().getPibLocator());
}catch (Exception e){
System.out.println("exception: " + e.getMessage());
}
}
}
@@ -1,29 +0,0 @@
package cn.minoa.dataRequestInterface;
// 在注册的界面未完成之前用于注册新用户
import org.json.JSONObject;
public class registerUser {
// 获取注册请求字符串
@SuppressWarnings("unused")
static private String getRegisterJson() {
JSONObject jsonObject = new JSONObject();
String mPubKey = "Bv0CsQcuCAR3Z2gwCANLRVkICH9+4yjVUHZaCAxjZXJ0LXJlcXVlc3QICf0AAAFv\nEUSBehQJGAECGQQANu6AFf0BJjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBANbFutCAZqFjHEa16tYvy4lBgi9/zixKWQzE9I72vaG2Imym+6KR30qkAQOK\nh0uE5RD2YsGhRK99rde+JOqIfk2/sunhp4nctOS5f4DeuOty58ekrO+Co9ZFmNBI\nmyk5i/hakjBEd/vdD7b1VadDRep5mWs3rgCinZOUfVaZ4oKqSws7ZWMvOSlRMOOi\nVzj53P4poY109S6aWmi3xKw/D76vfJapjdOB9Dg7S3rz0Rve1F/ajHCXWLt4XU3k\nUCiBn3Qmt6UD/MyDBaaUCfOvHTN6yVPtN6aOtYJVBAWt/P1ahLYhWkSm6KvrwMt0\nRzy2lw/lPriT99REItc/0wK6XwkCAwEAARZGGwEBHBcHFQgEd2doMAgDS0VZCAh/\nfuMo1VB2Wv0A/Sb9AP4PMjAxOTEyMTdUMDAzMTQw/QD/DzIwMTkxMjI3VDAwMzEz\nORf9AQCM+8WROXfi8WD9DydfLuSUxV0v3KW/Gn422/puDrkwwi1R2ogsAUc2O8pp\npuMLjWrQOTgE6ZTg80uWoDSUjjk44aMjkL2SAfp62vHRbGFx7+dckHAtF+DS6NH7\nX2vojFHOg6fksOE1M7XqLHmEEctZrFVSnQO7nB3DfRg+BqzZC/iy+8YAvTIvqA1c\nNsKYkmNITB80aM1v2H7fKnV4ZJpZnW71G5vbaPUseeklalQ2vEuBgWdd/1PL/0Ml\nI52npzqoeKAEpLp+vBwGN5ryGtWKB12nNimpMfevQAn/9BVIg59lZ7DIlE0sWmgW\nnwDxIXKebdViOejHlKwNAykxRRWw";
String commandString = "/register";
String userNameString = "oa_wefree";
String passWordString = "12345678";
String phoneString = "10000000006";
Integer levelInteger = 0;
try {
jsonObject.put("command", commandString);
jsonObject.put("username", userNameString);
jsonObject.put("password", passWordString);
jsonObject.put("phone", phoneString);
jsonObject.put("publicKey", mPubKey);
jsonObject.put("level", levelInteger);
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
}
@@ -0,0 +1,73 @@
package cn.minoa.model;
// 存储一个file或一个文件夹的属性
public class SingleFile {
//文件名
private String filename;
//文件路径
private String filepath;
//文件ID
private String fileId;
//文件创建时间
private Long time;
//文件类型
private String type;
//文件大小
private Long size;
public SingleFile(){
}
public SingleFile(String fileId){
this.fileId=fileId;
}
// public SingleFile(){}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
public String getFilepath() {
return filepath;
}
public void setFilepath(String filepath) {
this.filepath = filepath;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Long getSize() {
return size;
}
public void setSize(Long size) {
this.size = size;
}
}
@@ -0,0 +1,139 @@
package cn.minoa.util;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class EncryptionUtil {
public static String getMD5String(String str) {
try {
// 生成一个MD5加密计算摘要
MessageDigest md = MessageDigest.getInstance("MD5");
// 计算md5函数
md.update(str.getBytes("utf-8"));
// digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
//一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方)
String res = new BigInteger(1, md.digest()).toString(16);
System.out.println(str + " MD5加密结果: " + res);
return res;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public static String encryptBasedAES(String content) {
byte[] encrypt=encryptBasedAES(content,"123");
return ParseSystemUtil.parseByte2HexStr(encrypt);
}
// public static byte[] encryptBasedAES(String content) {
// return encryptBasedAES(content, "123");
// }
/**
* AES加密字符串
*
* @param content 需要被加密的字符串
* @param password 加密需要的密码
* @return 密文
*/
public static byte[] encryptBasedAES(String content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
// kgen.init(128, new SecureRandom(password.getBytes()));// 利用用户密码作为随机数初始化出
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes("utf-8"));
kgen.init(128, secureRandom);
//加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行
SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器
byte[] result = cipher.doFinal(byteContent);// 加密
return result;
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static String decryptBasedAES(String hexStr) {
byte[] byte2 = ParseSystemUtil.parseHexStr2Byte(hexStr);
try {
return new String(decryptBasedAES(byte2, "123"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
// public static byte[] decryptBasedAES(byte[] content) {
// return decryptBasedAES(content, "123");
// }
/**
* 解密AES加密过的字符串
*
* @param content AES加密过过的内容
* @param password 加密时的密码
* @return 明文
*/
public static byte[] decryptBasedAES(byte[] content, String password) throws UnsupportedEncodingException {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
// kgen.init(128, new SecureRandom(password.getBytes()));
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes("utf-8"));
kgen.init(128, secureRandom);
SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器
byte[] result = cipher.doFinal(content);
return result; // 明文
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
// 测试主函数
// public static void main(String[] args) throws Exception {
// String content = "哈哈哈";
// System.out.println("需要加密的内容:" + content);
// String enc=encryptBasedAES(content);
// System.out.println("加密后的16进制密文:" + enc);
// String dec=decryptBasedAES(enc);
// System.out.println("解密后的内容:" + dec);
// }
}
+47
View File
@@ -0,0 +1,47 @@
package cn.minoa.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileUtil {
/**
* 格式化时间
* @param format 格式化格式,基础格式为yyyy-MM-dd HH:mm:ss
* @param time 精确到ms
* @return
*/
public static String formatTime(String format, long time)
{
SimpleDateFormat df = new SimpleDateFormat(format);
return df.format(new Date(time));
}
// 后台返回的Long类型时间戳(精确到s)转日期
public static String timeToDateString(Long time){
String timeString = formatTime("yyyy-MM-dd HH:mm:ss", time*1000);
System.out.println(timeString);
return timeString;
}
// 文件大小根据具体大小,转成B/KB/M/G/T
public static String sizeToShowSize(Long size){
if(size<1024){
return size+" B";
}
Double sizeKB=size/1024.0;
if(sizeKB<1024){
return String.format("%.3f",sizeKB)+" KB";
}
Double sizeM=sizeKB/1024.0;
if(sizeM<1024){
return String.format("%.3f",sizeM)+" M";
}
Double sizeG=sizeM/1024.0;
if(sizeG<1024){
return String.format("%.3f",sizeG)+" G";
}
Double sizeT=sizeG/1024.0;
return String.format("%.3f",sizeT)+" T";
}
}
@@ -0,0 +1,76 @@
package cn.minoa.util;
import cn.minoa.MainApp;
import java.io.*;
import java.util.Properties;
public class KeyStorageUtil {
// 存数据
public static void setKeyName(String keyName){
InputStream inputStream = null;
OutputStream outputStream=null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream=new BufferedInputStream(new FileInputStream(MainApp.getClientPath()+ File.separator+"ndn"+File.separator+"settings.properties"));
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
settingProperties.setProperty("KeyName", keyName);
outputStream=new BufferedOutputStream(new FileOutputStream(MainApp.getClientPath()+ File.separator+"ndn"+File.separator+"settings.properties"));
settingProperties.store(outputStream,"修改配置文件");
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭输出流
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 取数据
public static String getKeyName() {
InputStream inputStream = null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream = new BufferedInputStream(new FileInputStream(MainApp.getClientPath() + File.separator + "ndn" + File.separator + "settings.properties"));
// inputStream = MainApp.class.getClassLoader().getResourceAsStream("/ndn/settings.properties");
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
String keyName = settingProperties.getProperty("KeyName");
return keyName;
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
@@ -1,16 +0,0 @@
package cn.minoa.util;
//import java.time.LocalDate;
//import javax.xml.bind.annotation.adapters.XmlAdapter;
//使得JAXB可以转换日期到XML
//public class LocalDateAdapter extends XmlAdapter<String,LocalDate> {
//
// public LocalDate unmarshal(String v) throws Exception{
// return LocalDate.parse(v);
// }
//
// public String marshal(LocalDate v) throws Exception{
// return v.toString();
// }
//}
@@ -0,0 +1,32 @@
package cn.minoa.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
public class LoggerUtil {
// 将文件名、文件操作、传输耗时等信息写入日志.
public static void insertFileAction(String filename, String fileaction, String usedtime) {
try {
File file = new File("./ndn/log.txt");
FileOutputStream fos = null;
if (!file.exists()) {
file.createNewFile();//如果文件不存在,就创建该文件
fos = new FileOutputStream(file);//首次写入获取
} else {
//如果文件已存在,那么就在文件末尾追加写入
fos = new FileOutputStream(file, true);//这里构造方法多了一个参数true,表示在文件末尾追加写入
}
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");//指定以UTF-8格式写入文件
osw.write("文件名:"+filename+" 文件操作:"+fileaction+" 文件耗时:"+usedtime);
osw.write("\r\n");
//写入完成关闭流
osw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,39 @@
package cn.minoa.util;
/**
* 进制转换工具类
*/
public class ParseSystemUtil {
/**将二进制转换成16进制
* @param buf
* @return
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**将16进制转换为二进制
* @param hexStr
* @return
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length()/2];
for (int i = 0;i< hexStr.length()/2; i++) {
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}
@@ -0,0 +1,207 @@
package cn.minoa.util;
import cn.minoa.dataRequestInterface.KeyManager;
import cn.minoa.dataRequestInterface.MinoaDataAPI;
import net.named_data.jndn.encoding.EncodingException;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.SafeBag;
import net.named_data.jndn.security.pib.Pib;
import net.named_data.jndn.security.pib.PibImpl;
import net.named_data.jndn.security.tpm.TpmBackEnd;
import net.named_data.jndn.security.v2.CertificateV2;
import net.named_data.jndn.util.Blob;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class SecretKeyManageUtil {
// 导出密钥
public static boolean exportSafeBag(String filepathname) {
try {
// 得到指定identity的证书(包含秘钥信息)
CertificateV2 certificateV2 = KeyManager.INSTANCE
.getCertification(MinoaDataAPI.keyChainNameString);
// 通过KeyChain导出SafeBag
// exportSafeBag支持设置密码
SafeBag safeBag = KeyManager.INSTANCE
.getKeyChain().exportSafeBag(certificateV2);
// 将safeBag进行编码
Blob blob = safeBag.wireEncode();
// 接着就可以将编码后的数据写入到一个文件当中
writeByteToFile(blob.getImmutableArray(), blob.size(),filepathname);
return true;
}catch (PibImpl.Error | Pib.Error | KeyChain.Error e){
e.printStackTrace();
System.out.println(e.getMessage());
return false;
}
}
// 导入密钥
public static String importSafeBag(String filepathname) {
try {
System.out.println("密钥文件:"+filepathname);
// 读取文件,得到字节数组,
// ByteBuffer bb = readByteBuffFromFile(filepathname);
byte[] b=readByteFromFile(filepathname);
if (b == null) {
return "The read file is empty.";
}
Blob blob=new Blob(b);
// 使用SafeBag的其中一种构造方法
SafeBag safeBag = new SafeBag(blob);
String name=safeBag.getCertificate().getName().toString();
System.out.println("导入文件的证书名称:"+name);
// 然后用KeyChain导入
// 如果exportSafeBag时设置了密码,importSafeBag的时候也要传入密码
KeyManager.INSTANCE
.getKeyChain()
.importSafeBag(safeBag);
return "success";
} catch (EncodingException | Pib.Error | TpmBackEnd.Error |
KeyChain.Error | PibImpl.Error | CertificateV2.Error | IOException e) {
// e.printStackTrace();
System.out.println(e.getMessage());
return e.getMessage();
}
}
public static ByteBuffer encodeValue(byte[] value) {
ByteBuffer byteBuffer = ByteBuffer.allocate(value.length);
byteBuffer.clear();
byteBuffer.get(value, 0, value.length);
return byteBuffer;
}
// 读取文件到一个byte
public static byte[] readByteFromFile(String filepathname) throws IOException {
File f = new File(filepathname);
if (!f.exists()) {
return null;
}
FileChannel channel = null;
FileInputStream fs = null;
try {
fs = new FileInputStream(f);
channel = fs.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
while ((channel.read(byteBuffer)) > 0) {
// do nothing
// System.out.println("reading");
}
return byteBuffer.array();
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 读取文件数据到一个bytebuff
public static ByteBuffer readByteBuffFromFile() throws IOException {
return readByteBuffFromFile("./ndn/SecretKey.txt");
}
/**
* NIO way
*
* @param
* @return
* @throws IOException
*/
public static ByteBuffer readByteBuffFromFile(String filepathname) throws IOException {
File f = new File(filepathname);
if (!f.exists()) {
return null;
}
FileChannel channel = null;
FileInputStream fs = null;
try {
fs = new FileInputStream(f);
channel = fs.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
while ((channel.read(byteBuffer)) > 0) {
// do nothing
// System.out.println("reading");
}
return byteBuffer;
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 写入byte数组到文件
private static void writeByteToFile(byte[] content, int len) {
writeByteToFile(content,len,"./ndn/SecretKeyMIN");
}
// 写入byte数组到文件
private static void writeByteToFile(byte[] content, int len,String filepathname) {
try {
File file = new File(filepathname);
FileOutputStream fos = null;
if (file.exists()) {
file.delete();
}
file.createNewFile();//如果文件不存在,就创建该文件
fos = new FileOutputStream(file);//首次写入获取
fos.write(content, 0, len);
//写入完成关闭流
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 写入字符串到文件
private static void writeStringToFile(String content) {
try {
File file = new File("./ndn/SecretKey.txt");
FileOutputStream fos = null;
if (file.exists()) {
file.delete();
}
file.createNewFile();//如果文件不存在,就创建该文件
fos = new FileOutputStream(file);//首次写入获取
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");//指定以UTF-8格式写入文件
osw.write(content);
//写入完成关闭流
osw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,6 +1,7 @@
package cn.minoa.view.home;
import cn.minoa.MainApp;
import cn.minoa.dataRequestInterface.DownLoadClientBasedFacePool;
import cn.minoa.dataRequestInterface.OrderInfo;
import cn.minoa.dataRequestInterface.ResponseData;
import cn.minoa.model.Email;
@@ -118,8 +119,20 @@ public class DealSingleReimbursementController {
}
System.out.println("开始下载... :"+pathfilename);
int flag=mainApp.downloadFileByPathfilename(pathfilename,localDirString);
if(flag==0) {
// int flag=mainApp.downloadFileByPathfilename(pathfilename,localDirString);
Long filelen= mainApp.getServerFileByteLength(pathfilename);
Integer sliceNum = (int)(filelen / mainApp.sliceSize);
if (filelen % mainApp.sliceSize != 0) {
sliceNum++;
}
Long startTime = System.currentTimeMillis();
DownLoadClientBasedFacePool downLoadClient = new DownLoadClientBasedFacePool(pathfilename,
localDirString,sliceNum,mainApp.threadNumberForFileTransfer);
// 下载文件
boolean res = downLoadClient.downloadData();
Long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - startTime) + "ms");
if(res) {
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("下载成功");
@@ -1,7 +1,9 @@
package cn.minoa.view.home;
import cn.minoa.MainApp;
import cn.minoa.dataRequestInterface.DownLoadClientBasedFacePool;
import cn.minoa.model.Reimbursement;
import cn.minoa.view.login.LoginOverviewController;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.ListView;
@@ -106,8 +108,21 @@ public class SingleReimbursementDetailsController {
}
System.out.println("开始下载... :"+pathfilename);
int flag=mainApp.downloadFileByPathfilename(pathfilename,localDirString);
if(flag==0) {
// int flag=mainApp.downloadFileByPathfilename(pathfilename,localDirString);
Long filelen= mainApp.getServerFileByteLength(pathfilename);
Integer sliceNum = (int)(filelen / mainApp.sliceSize);
if (filelen % mainApp.sliceSize != 0) {
sliceNum++;
}
Long startTime = System.currentTimeMillis();
DownLoadClientBasedFacePool downLoadClient = new DownLoadClientBasedFacePool(pathfilename,
localDirString,sliceNum,mainApp.threadNumberForFileTransfer);
// 下载文件
boolean res = downLoadClient.downloadData();
Long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - startTime) + "ms");
// 每个分片都下载成功
if(res) {
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("下载成功");
@@ -313,8 +313,8 @@ public class WrittenReimbursementController {
String pathfilename = reimbursementFilesList.get(i);
//上传该文件到服务器共享文件夹目录下
File file = new File(pathfilename);
Integer res=mainApp.uploadFileToServerSharedFolder(file);
if(res<0){
boolean res=mainApp.uploadFileToServerSharedFolder(file);
if(!res){
flag=false;
}
//将该文件信息[服务器文件路径地址]写入邮件信息中
@@ -0,0 +1,154 @@
package cn.minoa.view.login;
import cn.minoa.MainApp;
import cn.minoa.model.Loginer;
import cn.minoa.util.EncryptionUtil;
import java.io.*;
import java.util.Properties;
// 维持长登录状态
public class KeepLoginStatus {
public static void setLoginStatus(boolean flag){
InputStream inputStream = null;
OutputStream outputStream=null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream=new BufferedInputStream(new FileInputStream(MainApp.getClientPath()+ File.separator+"ndn"+File.separator+"settings.properties"));
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
if(flag==true){
settingProperties.setProperty("LoginStatus","true");
}else{
settingProperties.setProperty("LoginStatus","false");
}
outputStream=new BufferedOutputStream(new FileOutputStream(MainApp.getClientPath()+ File.separator+"ndn"+File.separator+"settings.properties"));
settingProperties.store(outputStream,"修改配置文件");
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭输出流
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void setLoginInfo(Loginer loginer){
InputStream inputStream = null;
OutputStream outputStream=null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream=new BufferedInputStream(new FileInputStream(MainApp.getClientPath()+ File.separator+"ndn"+File.separator+"settings.properties"));
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
settingProperties.setProperty("loginUserName", EncryptionUtil.encryptBasedAES(loginer.getUserName()));
settingProperties.setProperty("loginPassWord", EncryptionUtil.encryptBasedAES(loginer.getPassWord()));
outputStream=new BufferedOutputStream(new FileOutputStream(MainApp.getClientPath()+ File.separator+"ndn"+File.separator+"settings.properties"));
settingProperties.store(outputStream,"修改配置文件");
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭输出流
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static Loginer getLoginerInfo(){
Loginer m_loginer=new Loginer();
InputStream inputStream = null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream = new BufferedInputStream(new FileInputStream(MainApp.getClientPath() + File.separator + "ndn" + File.separator + "settings.properties"));
// inputStream = MainApp.class.getClassLoader().getResourceAsStream("/ndn/settings.properties");
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
String username = EncryptionUtil.decryptBasedAES(settingProperties.getProperty("loginUserName"));
String password = EncryptionUtil.decryptBasedAES(settingProperties.getProperty("loginPassWord"));
// System.out.println("username: " + username);
// System.out.println("password: " + password);
m_loginer.setUserName(username);
m_loginer.setPassWord(password);
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return m_loginer;
}
public static boolean getLogineStatus(){
InputStream inputStream = null;
try {
//如果 classPath 不存在,则获取的输入流会为 null
inputStream = new BufferedInputStream(new FileInputStream(MainApp.getClientPath() + File.separator + "ndn" + File.separator + "settings.properties"));
// inputStream = MainApp.class.getClassLoader().getResourceAsStream("/ndn/settings.properties");
if (inputStream == null) {
System.out.println("没有找到配置文件...");
}
Properties settingProperties = new Properties();
settingProperties.load(inputStream);
String LoginStatus = settingProperties.getProperty("LoginStatus");
if(LoginStatus.equals("true")){
return true;
}else{
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
//关闭输入流
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
@@ -6,16 +6,26 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import cn.minoa.dataRequestInterface.MinoaDataAPI;
import cn.minoa.dataRequestInterface.*;
import cn.minoa.model.Loginer;
import cn.minoa.util.EncryptionUtil;
import cn.minoa.util.KeyStorageUtil;
import cn.minoa.util.SecretKeyManageUtil;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import net.named_data.jndn.security.KeyChain;
import net.named_data.jndn.security.pib.Pib;
import net.named_data.jndn.security.pib.PibImpl;
import net.named_data.jndn.security.tpm.Tpm;
import net.named_data.jndn.security.tpm.TpmBackEnd;
import net.named_data.jndn.security.v2.CertificateV2;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import cn.minoa.MainApp;
import cn.minoa.dataRequestInterface.OrderInfo;
import cn.minoa.dataRequestInterface.ResponseData;
import cn.minoa.model.Person;
import cn.minoa.model.SingleMessage;
import cn.minoa.model.SingleNotice;
@@ -90,22 +100,67 @@ public class LoginOverviewController {
private void handleLogin() {
// 实例化
// mainApp.minoaDataAPI = new MinoaDataAPI(mainApp);
String userNameString=userNameFiled.getText().trim();
String passWordString=passwordFiled.getText().trim();
if(userNameString.equals("")){
return ;
}
// 登录之前先查看本地是否有该用户拥有的证书
String keyChainNameString="/"+userNameString;
try {
if(!KeyManager.INSTANCE.isInKeyChain(keyChainNameString)){
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("密钥错误");
alert.setHeaderText("本地没有你的密钥");
alert.setContentText("请导入密钥/证书。");
alert.showAndWait();
return;
}
} catch (Pib.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
return;
}
// 每次手动登录之前,将keyChain初始化一下
MinoaDataAPI.keyChainNameString=keyChainNameString;
try {
KeyManager.INSTANCE.initKeyChain(keyChainNameString);
} catch (Pib.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) {
error.printStackTrace();
}
// 登录验证
String loginString = getLoginJsonString();
boolean isRight = checkPass(loginString);
if (isRight) {
// 持久化保存当前用户名和密码
keepLoginInfo(true,userNameString,passWordString);
// 持久化保存当前keyName
KeyStorageUtil.setKeyName(keyChainNameString);
// 修改登录状态
mainApp.isNeedKnowLoginStatus=true;
mainApp.iniShow();
} else {
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Wrong UserName or Password");
alert.setHeaderText("Please correct UserName or Password.");
alert.setContentText("Please correct UserName or Password.");
alert.setTitle("用户名或密码错误");
alert.setHeaderText("请核对用户名或密码");
alert.setContentText("请核对用户名或密码。\n" +
"如果你故意导入了首字段与用户名相同的密钥证书,但" +
"该证书是非法生成的,也将弹出该弹窗!!!");
alert.showAndWait();
}
}
private boolean checkPass(String loginJsonString) {
// 将账号密码保存在本地
private void keepLoginInfo(boolean flag,String username,String passord){
Loginer m_loginer=new Loginer();
m_loginer.setUserName(username);
m_loginer.setPassWord(passord);
KeepLoginStatus.setLoginStatus(flag);
KeepLoginStatus.setLoginInfo(m_loginer);
}
public boolean checkPass(String loginJsonString) {
System.out.println("checking your password...");
boolean flag = false;
// 发送数据请求
@@ -156,7 +211,7 @@ public class LoginOverviewController {
}
// 请求服务器某文件的大小:返回-1表示没有该文件或登录失效
public Integer getServerFileLength(String filename) {
public Long getServerFileLength(String filename) {
// 发送数据请求
Long seqLong = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
@@ -179,196 +234,70 @@ public class LoginOverviewController {
try {
dataString = jsonObject.getString("data");
JSONObject dataJsonObject = new JSONObject(dataString);
Integer fileSize= dataJsonObject.getInt("fileSize");
Long fileSize= dataJsonObject.getLong("fileSize");
return fileSize;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return -1;
}
}
return -1;
return (long)-1;
}
// 下载文件[返回0:已经成功接收所有回执数据并写入本地文件]
public Integer downloadFile(String filename) {
// 发送数据请求
Long seqLong = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
orderInfo.setJsonString(getFileInfoJson(filename));
mainApp.minoaDataAPI.executeOrder("/fileInfo", orderInfo);
// 获取头像信息
ResponseData responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
JSONObject jsonObject = responseData.praseRequestData();
System.out.println("fileInfo-JSON: " + jsonObject.toString());
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (codeInteger == 200) {
String dataString;
try {
dataString = jsonObject.getString("data");
JSONObject dataJsonObject = new JSONObject(dataString);
Integer sliceNumInteger;
sliceNumInteger = dataJsonObject.getInt("sliceNum");
// 根据分片信息获取每个分片,并合并成一个完整比特流
Integer flagInteger = 0;
for (int i = 0; i < sliceNumInteger; i++) {
flagInteger += downLoadFileBySlice(filename, i);
// 导入密钥
@FXML
private void importSafeBag(){
// SecretKeyManageUtil.testSecretKey(KeyStorageUtil.getKeyName());
// System.out.println("#####test end#####");
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("选择密钥文件");
Stage selectFileStage = new Stage();
File file = fileChooser.showOpenDialog(selectFileStage);
if (file != null) {
// 文件不为空,且不是文件夹
if (file.isFile()) {
//判断文件长度是否为0
System.out.println("file length: " + file.length());
if (file.length() == 0) {
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("空文件错误");
alert.setHeaderText("您选择的是一个空文件");
alert.setContentText("您选择的是一个空文件,请重新选择。");
alert.showAndWait();
return;
}
System.out.println("下载分片的消息回执[0表示全部数据分片已经被写入本地]: " + flagInteger);
return flagInteger;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 1;
} else {
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("文件类型错误");
alert.setHeaderText("你的文件类型错误");
alert.setContentText("请确保你选中的是一个文件而非文件夹。");
alert.showAndWait();
return ;
}
}else{
return ;
}
// 将所选文件导入密钥
String res= SecretKeyManageUtil.importSafeBag(file.getAbsolutePath());
if(res.equals("success")){
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("密钥导入成功");
alert.setHeaderText("密钥导入成功");
alert.setContentText("你已成功导入密钥");
alert.showAndWait();
}else{
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("密钥导入失败");
alert.setHeaderText("密钥导入失败");
alert.setContentText("由于如下原因,密钥导入时出现了问题:\n"+res);
alert.showAndWait();
}
return 1;
}
/*
* @param filename 要下载的文件的“服务器路径+文件名称”,即写入请求的名称
*
* @param localDir 要下载文件到的本地地址
*
* @param localName 要下载的文件重命名之后的本地名称
*
* @return 0表示已经成功接收所有回执数据并写入本地文件,否则出现error
*
* 目的是下载头像到指定路径,并重命名之。
*/
private Integer downloadRenamedFileToSpecifiedDir(String filename, String localDir, String localName) {
// 发送数据请求
Long seqLong = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
orderInfo.setJsonString(getFileInfoJson(filename));
mainApp.minoaDataAPI.executeOrder("/fileInfo", orderInfo);
// 获取头像信息
ResponseData responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
JSONObject jsonObject = responseData.praseRequestData();
System.out.println("fileInfo-JSON: " + jsonObject.toString());
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (codeInteger == 200) {
String dataString;
try {
dataString = jsonObject.getString("data");
JSONObject dataJsonObject = new JSONObject(dataString);
Integer sliceNumInteger;
sliceNumInteger = dataJsonObject.getInt("sliceNum");
// 根据分片信息获取每个分片,并合并成一个完整比特流
Integer flagInteger = 0;
for (int i = 0; i < sliceNumInteger; i++) {
flagInteger += downLoadFileBySlice(filename, i, localDir, localName);
}
System.out.println("下载分片的消息回执[0表示全部数据分片已经被写入本地]: " + flagInteger);
return flagInteger;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 1;
}
}
return 1;
}
/*
* @param filename 要下载的文件的“服务器路径+文件名称”,即写入请求的名称
*
* @param localDir 要下载文件到的本地地址
*
* @return 0表示已经成功接收所有回执数据并写入本地文件,否则出现error
*
* .下载服务器文件到本地指定目录下
*/
public Integer downloadFileToSpecifiedDir(String filename, String localDir) {
// 下载到本地的文件名称
String localName = getPureFileName(filename);
// 发送数据请求
Long seqLong = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
orderInfo.setJsonString(getFileInfoJson(filename));
mainApp.minoaDataAPI.executeOrder("/fileInfo", orderInfo);
// 获取文件信息
ResponseData responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
JSONObject jsonObject = responseData.praseRequestData();
System.out.println("fileInfo-JSON: " + jsonObject.toString());
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (codeInteger == 200) {
String dataString;
try {
dataString = jsonObject.getString("data");
JSONObject dataJsonObject = new JSONObject(dataString);
Integer sliceNumInteger;
sliceNumInteger = dataJsonObject.getInt("sliceNum");
// 根据分片信息获取每个分片,并合并成一个完整比特流
Integer flagInteger = 0;
for (int i = 0; i < sliceNumInteger; i++) {
flagInteger += downLoadFileBySlice(filename, i, localDir, localName);
}
System.out.println("下载分片的消息回执[0表示全部数据分片已经被写入本地]: " + flagInteger);
return flagInteger;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return 1;
}
}
return 1;
}
// 请求文件分片数据=>返回0表示分片数据被成功下载
public Integer downLoadFileBySlice(String filename, Integer sliceNo, String localDir, String localName) {
Integer flagInteger;
// 发送数据请求
Long seqLong = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
orderInfo.setJsonString(getDownloadFileJson(filename, sliceNo));
mainApp.minoaDataAPI.executeOrder("/downloadFile", orderInfo, localDir, localName);
// 获取头像信息
ResponseData responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
// JSONObject jsonObject=responseData.praseRequestData();
System.out.println("downloadFileSlice-JSON: " + responseData.getResponseJsonDataString());
flagInteger = Integer.parseInt(responseData.getResponseJsonDataString());
return flagInteger;
}
// 生成本地文件=>没有用到
// public void creatLocalFile(String filename,byte[] fileBytes) {
// FileOutputStream out;
// try {
// out = new FileOutputStream(new File(filename));
// try {
// out.write(fileBytes);
// out.flush();
// System.out.println("download success");
// out.close();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// } catch (FileNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// 根据包含路径的文件名获取纯文件名[linux下]
public String getPureFileName(String pathfilename) {
// 标记最后一个/的下标
@@ -387,40 +316,6 @@ public class LoginOverviewController {
}
}
// 根据包含路径的文件名获取纯文件名
// public String getPureFileName(String pathfilename) {
// // 文件名称切割
// while (pathfilename.indexOf('/') > 0) {
// pathfilename = pathfilename.substring(pathfilename.indexOf('/') + 1, pathfilename.length());
// }
// System.out.println("pure file name: " + pathfilename);
// return pathfilename;
// }
// 合并两个Byte[]
// public Byte[] byteMerger(Byte[] bt1, Byte[] bt2){
// Byte[] bt3 = new Byte[bt1.length+bt2.length];
// System.arraycopy(bt1, 0, bt3, 0, bt1.length);
// System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
// return bt3;
// }
// 请求文件分片数据=>返回0表示分片数据被成功下载
private Integer downLoadFileBySlice(String filename, Integer sliceNo) {
Integer flagInteger;
// 发送数据请求
Long seqLong = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
orderInfo.setJsonString(getDownloadFileJson(filename, sliceNo));
mainApp.minoaDataAPI.executeOrder("/downloadFile", orderInfo);
// 获取头像信息
ResponseData responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
// JSONObject jsonObject=responseData.praseRequestData();
System.out.println("downloadFileSlice-JSON: " + responseData.getResponseJsonDataString());
flagInteger = Integer.parseInt(responseData.getResponseJsonDataString());
return flagInteger;
}
// 获取要下载的文件信息
public String getFileInfoJson(String filename) {
JSONObject jsonObject = new JSONObject();
@@ -440,22 +335,18 @@ public class LoginOverviewController {
return jsonObject.toString();
}
// 获取要下载的文件信息
private String getDownloadFileJson(String filename, Integer sliceNo) {
public String getLoginJsonString(String userNameString,String passWordString) {
JSONObject jsonObject = new JSONObject();
String commandString = "/downloadFile";
String usernameString = mainApp.loginer.getUserName();
String uuidString = mainApp.loginer.getUuid();
String filenameString = filename;
Integer sliceNoInteger = sliceNo;
String commandString = "/login";
// 对密码进行哈希加密
passWordString= EncryptionUtil.getMD5String(passWordString);
mainApp.loginer.setUserName(userNameString);
mainApp.loginer.setPassWord(passWordString);
try {
jsonObject.put("command", commandString);
jsonObject.put("username", usernameString);
jsonObject.put("uuid", uuidString);
jsonObject.put("filename", filenameString);
jsonObject.put("sliceNo", sliceNoInteger);
jsonObject.put("username", userNameString);
jsonObject.put("password", passWordString);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
@@ -467,14 +358,8 @@ public class LoginOverviewController {
String commandString = "/login";
String userNameString = userNameFiled.getText().trim();
String passWordString = passwordFiled.getText().trim();
if (userNameString == null || passWordString == null) {
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("UserName or Password is null");
alert.setHeaderText("Please correct UserName or Password.");
alert.setContentText("Please correct UserName or Password.");
alert.showAndWait();
}
// 对密码进行哈希加密
passWordString= EncryptionUtil.getMD5String(passWordString);
mainApp.loginer.setUserName(userNameString);
mainApp.loginer.setPassWord(passWordString);
try {
@@ -1076,112 +961,51 @@ public class LoginOverviewController {
return jsonObject.toString();
}
// //"获取2019年9月1日之后与该选中人的100条互发消息"
// private String getGetRTMsgLogJson(Person selectedPerson) {
// JSONObject jsonObject =new JSONObject();
// String commandString="/getRTMsgLog";
// String userNameString=mainApp.loginer.getUserName();
// String uuidString=mainApp.loginer.getUuid();
// String peerString=selectedPerson.getUserName();
// Long timestampLong = null;
// try {
// timestampLong=get20190901();
// } catch (ParseException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
// //期望获取的信息条数
// Integer limitInteger=100;
// //0表示时间节点之后,1表示之前
// Integer directInteger=0;
// try {
// jsonObject.put("command", commandString);
// jsonObject.put("username", userNameString);
// jsonObject.put("uuid", uuidString);
// jsonObject.put("peer", peerString);
// jsonObject.put("timestamp", timestampLong);
// jsonObject.put("limit", limitInteger);
// jsonObject.put("direct", directInteger);
// } catch (Exception e) {
// // TODO: handle exception
// System.out.println("exception: " + e.getMessage());
// }
// return jsonObject.toString();
// }
//获取上传文件的json格式
public String getUploadFile(String filename, Integer offset) {
JSONObject jsonObject = new JSONObject();
String commandString = "/uploadFile";
String usernameString = mainApp.loginer.getUserName();
String uuidString = mainApp.loginer.getUuid();
String filenameString = filename;
Integer offsetInteger = offset;
try {
jsonObject.put("command", commandString);
jsonObject.put("username", usernameString);
jsonObject.put("uuid", uuidString);
jsonObject.put("filename", filenameString);
jsonObject.put("offset", offsetInteger);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
// 调试输出
System.out.println("getUploadFile: "+jsonObject.toString());
return jsonObject.toString();
}
/*
* .文件上传操作
* @param serverpath 将该文件上传到的指定服务器路径
* @param file 要上传的本地文件
* @return 返回0表示传输成功;返回-1表示传输失败
* @param filename 要下载的文件的“服务器路径+文件名称”,即写入请求的名称
*
* @param localDir 要下载文件到的本地地址
*
* @param localName 要下载的文件重命名之后的本地名称
*
* @return 0表示已经成功接收所有回执数据并写入本地文件,否则出现error
*
* 目的是下载头像到指定路径,并重命名之。
*/
public Integer sendFileToServer(File file, String serverpath) {
//获取要上传文件的文件长度,计算上传次数
long filelen = file.length();
int cycle = (int) filelen / mainApp.sliceSize;
int remainder=(int)filelen%mainApp.sliceSize;
if((cycle>0)&&(remainder==0)) {
cycle--;
private Integer downloadRenamedFileToSpecifiedDir(String filename, String localDir, String localName){
Long filelen=getServerFileLength(filename);
Integer sliceNum = (int)(filelen / mainApp.sliceSize);
if (filelen % mainApp.sliceSize != 0) {
sliceNum++;
}
System.out.println("file-len: " + filelen);
System.out.println("cycle: " + cycle);
//发送上传命令给上传接口,接口自行取本地数据
int flagSuccess = 0; //记录收到200回复的次数
for (int i = 0; i <= cycle; i++) {
OrderInfo orderInfo = new OrderInfo();
ResponseData responseData = new ResponseData();
Long seqLong = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLong);
//此时传入的文件路径是windows下的绝对路径
orderInfo.setJsonString(getUploadFile(file.getAbsolutePath(), i * mainApp.sliceSize));
mainApp.minoaDataAPI.executeOrder("/uploadFile", orderInfo, serverpath);
responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
// System.out.println("上传文件的数据回执(200表示成功)"+responseData.getResponseJsonDataString());
JSONObject jsonObject = responseData.praseRequestData();
responseData.printSelf();
// 解析数据
Integer codeInteger = null;
try {
codeInteger = jsonObject.getInt("code");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (codeInteger == 200) {
flagSuccess++;
}
}
//每个分片都上传成功
if (flagSuccess == (cycle + 1)) {
System.out.println("已成功将文件" + file.getAbsolutePath() + "上传至服务器" + serverpath + "目录下。");
Long startTime = System.currentTimeMillis();
DownLoadClientBasedFacePool downLoadClient = new DownLoadClientBasedFacePool(filename,
localDir,sliceNum,mainApp.threadNumberForFileTransfer);
// 下载文件
boolean res = downLoadClient.downloadData();
Long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - startTime) + "ms");
// 每个分片都下载成功
if (res) {
// 重命名该文件
String fromPathName=localDir
+MinoaDataAPI.getPureFileName(filename);
String toPathName=localDir+localName;
renameLocalFile(fromPathName,toPathName);
return 0;
} else {
System.out.println("由于未知原因,本地文件" + file.getAbsolutePath() + "上传服务器失败。");
}else{
return -1;
}
}
// 重命名本地文件
private void renameLocalFile(String fromPathName,String toPathName){
File file=new File(fromPathName);
if (file.exists()) {
File toPathNameFile= new File(toPathName);
file.renameTo(toPathNameFile);
}else{
System.out.println("要重命名的文件不存在");
}
}
}
@@ -0,0 +1,294 @@
package cn.minoa.view.login;
// 与区块链建立TCP连接,发送注册请求
import cn.minoa.MainApp;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import java.net.Socket;
public class NDNBlockChainConnectClient {
private String NDNBlockChainIPAddress;
private Integer NDNBlockChainPortAddress;
public NDNBlockChainConnectClient(){
// this.NDNBlockChainIPAddress="116.77.74.144";
// this.NDNBlockChainIPAddress="121.15.171.86";
// this.NDNBlockChainPortAddress=8010;
this.NDNBlockChainIPAddress= MainApp.NDNBlockChainIPAddress;
System.out.println("区块链IP"+ MainApp.NDNBlockChainIPAddress);
this.NDNBlockChainPortAddress= MainApp.NDNBlockChainPortAddress;
System.out.println("区块链Port"+ MainApp.NDNBlockChainPortAddress);
}
public NDNBlockChainConnectClient(String ipAddress, Integer portAddress){
this.NDNBlockChainIPAddress= ipAddress;
this.NDNBlockChainPortAddress=portAddress;
}
// 添加白名单
public String addWhiteUser(String phone){
// 获取注册数组
byte[] registerByte=getBlockChainWhiteBuffer(phone);
System.out.println("whiteuser length: "+registerByte.length);
// 通过TCP连接区块链后台
Socket blockchainClient;
try {
blockchainClient=new Socket(NDNBlockChainIPAddress,NDNBlockChainPortAddress);
} catch (IOException e) {
e.printStackTrace();
System.out.println("连接不可达:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress);
return e.getMessage();
}
System.out.println("已成功建立TCP连接:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress
+"; 远程主机地址:"+blockchainClient.getRemoteSocketAddress());
try {
OutputStream outToServer = blockchainClient.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.write(registerByte);
InputStream inFromServer = blockchainClient.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("正在等待服务器响应...");
byte[] res = new byte[4];
in.read(res);
int resSize = Bytes2Int_LE(res);
System.out.println("返回值长度为:"+ resSize);
res = new byte[resSize];
in.read(res);
System.out.println("返回值内容为:" + new String(res));
blockchainClient.close();
System.out.println("已关闭此次TCP连接:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress);
// System.out.println("服务器响应: " );
// 解析返回来的数据,如果是200,就返回true
try {
String resString=new String(res);
System.out.println("resString: "+resString);
JSONObject resObject=new JSONObject(resString);
int resCode=resObject.getInt("StatusCode");
String message=resObject.getString("Message");
if(resCode==200){
System.out.println("区块链添加白名单成功:"+phone);
return "true";
}else{
return message;
}
} catch (JSONException e) {
e.printStackTrace();
return e.getMessage();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("添加白名单时数据交换出错:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress);
return e.getMessage();
}
// return true;
}
// 注册用户
public String registeNewUser(String username,String phone,String pubkey){
// 获取注册数组
byte[] registerByte=getBlockChainRegisterBuffer(username,phone, pubkey);
System.out.println("register length: "+registerByte.length);
// 通过TCP连接区块链后台
Socket blockchainClient;
try {
blockchainClient=new Socket(NDNBlockChainIPAddress,NDNBlockChainPortAddress);
} catch (IOException e) {
e.printStackTrace();
System.out.println("连接不可达:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress);
return e.getMessage();
}
System.out.println("已成功建立TCP连接:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress
+"; 远程主机地址:"+blockchainClient.getRemoteSocketAddress());
try {
OutputStream outToServer = blockchainClient.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.write(registerByte);
InputStream inFromServer = blockchainClient.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("正在等待服务器响应...");
byte[] res = new byte[4];
in.read(res);
int resSize = Bytes2Int_LE(res);
System.out.println("返回值长度为:"+ resSize);
res = new byte[resSize];
in.read(res);
System.out.println("返回值内容为:" + new String(res));
System.out.println("服务器响应: " );
blockchainClient.close();
System.out.println("已关闭此次TCP连接:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress);
// System.out.println("服务器响应: " );
// 解析返回来的数据,如果是200,就返回true
try {
String resString=new String(res);
System.out.println("resString: "+resString);
JSONObject resObject=new JSONObject(resString);
int resCode=resObject.getInt("StatusCode");
String message=resObject.getString("Message");
if(resCode==200){
System.out.println("区块链注册用户成功:"+username);
return "true";
}else{
return message;
}
} catch (JSONException e) {
e.printStackTrace();
return e.getMessage();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("注册时数据交换出错:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress);
return e.getMessage();
}
}
private byte[] getBlockChainRegisterBuffer(String username,String phone, String pubkey) {
String registerString=getBlockChainRegisterJsonString(username,phone, pubkey);
System.out.println("json: "+registerString);
int jsonLen = registerString.getBytes().length;
System.out.println("json len: "+jsonLen);
byte[] registerByte=new byte[jsonLen+4];
// System.arraycopy(intToBytesLittle(jsonLen),0,
// registerByte,0,4);
System.arraycopy(intToBytesLittle(jsonLen),0,
registerByte,0,4);
try {
System.arraycopy(registerString.getBytes("utf-8"),
0,registerByte,4,jsonLen);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return registerByte;
}
private byte[] getBlockChainWhiteBuffer(String phone) {
String registerString=getBlockChainWhiteUserJsonString(phone);
System.out.println("json: "+registerString);
int jsonLen = registerString.getBytes().length;
System.out.println("json len: "+jsonLen);
byte[] registerByte=new byte[jsonLen+4];
// System.arraycopy(intToBytesLittle(jsonLen),0,
// registerByte,0,4);
System.arraycopy(intToBytesLittle(jsonLen),0,
registerByte,0,4);
try {
System.arraycopy(registerString.getBytes("utf-8"),
0,registerByte,4,jsonLen);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return registerByte;
}
/**
* 以小端模式将int转成byte[]
*
* @param value
* @return
*/
public static byte[] intToBytesLittle(int value) {
byte[] src = new byte[4];
src[3] = (byte) ((value >> 24) & 0xFF);
src[2] = (byte) ((value >> 16) & 0xFF);
src[1] = (byte) ((value >> 8) & 0xFF);
src[0] = (byte) (value & 0xFF);
return src;
}
/**
* 以大端模式将int转成byte[]
*
* @param value
* @return
*/
public static byte[] intToBytesBig(int value) {
byte[] src = new byte[4];
src[0] = (byte) ((value >> 24) & 0xFF);
src[1] = (byte) ((value >> 16) & 0xFF);
src[2] = (byte) ((value >> 8) & 0xFF);
src[3] = (byte) (value & 0xFF);
return src;
}
/**
* 转换byte数组为int(小端)
* @return
* @note 数组长度至少为4,按小端方式转换,即传入的bytes是小端的,按这个规律组织成int
*/
public int Bytes2Int_LE(byte[] bytes){
if(bytes.length < 4)
return -1;
int iRst = (bytes[0] & 0xFF);
iRst |= (bytes[1] & 0xFF) << 8;
iRst |= (bytes[2] & 0xFF) << 16;
iRst |= (bytes[3] & 0xFF)<< 24;
return iRst;
}
// 从前端界面获得登录数据并转换成json格式
private String getBlockChainWhiteUserJsonString(String phone) {
JSONObject jsonObject = new JSONObject();
String typeString = "whiteUser";
String commandString = "addWhiteUser";
String RealNameString = "王锋";
Integer GenderInteger=0;
String IDCardString="";
try {
jsonObject.put("Type", typeString);
jsonObject.put("Command", commandString);
jsonObject.put("RealName",RealNameString);
jsonObject.put("Phone",phone);
jsonObject.put("Gender",GenderInteger);
jsonObject.put("IDCard",IDCardString);
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
// 从前端界面获得登录数据并转换成json格式
private String getBlockChainRegisterJsonString(String username,String phone, String pubkey) {
JSONObject jsonObject = new JSONObject();
String typeString = "user-act";
String commandString = "Registry";
String pubkeyString = pubkey;
String prefixString="/"+username;
Integer level=0;
String timestamp="";
String IDCard="";
String realname="";
String aboutMe="";
String face="";
String print="";
String iris="";
String other="";
String sig="";
try {
jsonObject.put("Type", typeString);
jsonObject.put("Command", commandString);
jsonObject.put("Pubkey", pubkeyString);
jsonObject.put("Prefix",prefixString);
jsonObject.put("Level",level);
jsonObject.put("Timestamp",timestamp);
jsonObject.put("Username",username);
jsonObject.put("Realname",realname);
jsonObject.put("Phone",phone);
jsonObject.put("IDcard",IDCard);
jsonObject.put("AboutMe",aboutMe);
jsonObject.put("Face",face);
jsonObject.put("Print",print);
jsonObject.put("Iris",iris);
jsonObject.put("Other",other);
jsonObject.put("Sig",sig);
} catch (Exception e) {
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
}
@@ -2,6 +2,8 @@ package cn.minoa.view.mine;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.LinkedList;
/*
* 数据格式说明:
@@ -11,7 +13,12 @@ import java.util.LinkedList;
* .前端一个listview表项是一个pane,其id是"路径+纯文件名+@文件类型"
*/
import java.util.List;
import java.util.Map;
import cn.minoa.model.SingleFile;
import cn.minoa.util.FileUtil;
import cn.minoa.util.StringByteLengthUtil;
import cn.minoa.view.login.LoginOverviewController;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -38,6 +45,8 @@ public class MyCloudFileController {
private String currentPath;
// 当前路径下的文件列表[path+file+@type]
private List<String> filePathnameList;
// 当前文件列表对应的文件具体信息,key是filePathnameList中的表项
private Map<String, SingleFile> detailedFileListMap;
@FXML
private Text pathText;
@@ -53,6 +62,7 @@ public class MyCloudFileController {
// TODO Auto-generated constructor stub
currentPath = "/";
filePathnameList = new LinkedList<String>();
detailedFileListMap=new HashMap<String, SingleFile>();
}
@FXML
@@ -183,7 +193,7 @@ public class MyCloudFileController {
}else{
serverPathname=currentPath+"/"+file.getName();
}
Integer fileServerLength=mainApp.getServerFileByteLength(serverPathname);
Long fileServerLength=mainApp.getServerFileByteLength(serverPathname);
System.out.println("fileServerLength: "+fileServerLength);
if(fileServerLength<0){
//文件未成功创建
@@ -259,7 +269,32 @@ public class MyCloudFileController {
}
public void makeDir(String foldername) {
//封死空文件夹
if(foldername.trim().equals("")){
return ;
}
// 封掉命名为/的文件夹
if(foldername.trim().equals("/")){
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("新建失败");
alert.setHeaderText("新建文件夹失败");
alert.setContentText("文件夹名称不许为\"/\"哦~");
alert.showAndWait();
return ;
}
foldername = currentPath + "/" + foldername;
//封死在用户跟目录下创建share或cache文件夹
if(foldername.equals("/share")||foldername.equals("/cache")||
foldername.equals("//share")||foldername.equals("//cache")){
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("新建失败");
alert.setHeaderText("新建文件夹失败");
alert.setContentText("根目录下不允许创建命名为share或cache的文件夹。");
alert.showAndWait();
return ;
}
// 请求数据
OrderInfo orderInfo = new OrderInfo();
ResponseData responseData = new ResponseData();
@@ -306,6 +341,16 @@ public class MyCloudFileController {
// 删除选中项按钮=>只支持删除普通文件
@FXML
private void deleteSelectedItem() {
//判断是否选择了文件
if(fileList.getSelectionModel().getSelectedItem()==null){
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("文件未选择");
alert.setHeaderText("文件未选择");
alert.setContentText("请先在文件列表中选择一个文件。");
alert.showAndWait();
return;
}
System.out.println("发送了删除请求到服务器...");
// 获取选中的文件
Pane pane = fileList.getSelectionModel().getSelectedItem();
@@ -356,36 +401,20 @@ public class MyCloudFileController {
}
// 下载选中项按钮,下载文件到缺省本地目录[E盘根目录]
// @FXML
// private void downloadSelectedItem() {
// Pane pane=fileList.getSelectionModel().getSelectedItem();
// String pathfilename=getPathFileName(pane.getId());
// System.out.println("开始下载... :"+pathfilename);
// int flag=mainApp.downloadFileByPathfilename(pathfilename);
// if(flag==0) {
//// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
// Alert alert = new Alert(AlertType.INFORMATION);
// alert.setTitle("下载成功");
// alert.setHeaderText("下载文件成功");
// alert.setContentText("您请求的文件数据已经被全部下载到本地,"
// + "如有发现打开异常或数据内容并非所求,说明出现了服务器数据请求问题。"
// + "您的文件默认保存位置为:"+mainApp.fileLocalPath);
// alert.showAndWait();
// }else {
//// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
// Alert alert = new Alert(AlertType.ERROR);
// alert.setTitle("下载失败");
// alert.setHeaderText("下载文件失败");
// alert.setContentText("本地文件数据写入失败,请检查是否有权限访问默认存储位置。"
// + "您的文件默认保存位置为:"+mainApp.fileLocalPath);
// alert.showAndWait();
// }
// }
// 下载选中项按钮
@FXML
private void downloadSelectedItem() {
// 判断是否选择了文件
if(fileList.getSelectionModel().getSelectedItem()==null){
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("文件未选择");
alert.setHeaderText("文件未选择");
alert.setContentText("请先在文件列表中选择一个文件。");
alert.showAndWait();
return;
}
// 选择要下载到的文件夹
String localDirString = mainApp.fileLocalPath;
DirectoryChooser directoryChooser = new DirectoryChooser();
@@ -420,7 +449,7 @@ public class MyCloudFileController {
}
// 下载文件之后,通过获取服务器的文件大小,与下载到本地的文件大小对比
// 判断是否传输成功
Integer fileServerLength=mainApp.getServerFileByteLength(pathfilename);
Long fileServerLength=mainApp.getServerFileByteLength(pathfilename);
System.out.println("fileServerLength: "+fileServerLength);
String localfilename=localDirString+getPureFileNameFromLinux(pathfilename);
File localfile=new File(localfilename);
@@ -450,23 +479,6 @@ public class MyCloudFileController {
alert.setContentText("文件数据未能全部写入本地。" + "您的文件保存位置为:" +localDirString);
alert.showAndWait();
}
// int flag = mainApp.downloadFileByPathfilename(pathfilename,localDirString);
// if (flag == 0) {
//// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
// Alert alert = new Alert(AlertType.INFORMATION);
// alert.setTitle("下载成功");
// alert.setHeaderText("下载文件成功");
// alert.setContentText("您请求的文件数据已经被全部下载到本地," + "如有发现打开异常或数据内容并非所求,说明出现了服务器数据请求问题。" + "您的文件保存位置为:"
// + localDirString);
// alert.showAndWait();
// } else {
//// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
// Alert alert = new Alert(AlertType.ERROR);
// alert.setTitle("下载失败");
// alert.setHeaderText("下载文件失败");
// alert.setContentText("本地文件数据写入失败,请检查是否有权限访问文件存储位置。" + "您的文件保存位置为:" +localDirString);
// alert.showAndWait();
// }
}
// 根据包含路径的文件名获取纯文件名[linux下]
@@ -524,9 +536,9 @@ public class MyCloudFileController {
return jsonObject.toString();
}
// 列出某目录下的所有文件
// 列出某目录下的所有文件【非文件夹】
private boolean lsFolder(String foldername) {
System.out.println("foldername: " + foldername);
System.out.println("罗列foldername下文件: " + foldername);
// 请求数据
OrderInfo orderInfo = new OrderInfo();
ResponseData responseData = new ResponseData();
@@ -546,12 +558,15 @@ public class MyCloudFileController {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (codeInteger == 201) {
filePathnameList.clear();
detailedFileListMap.clear();
if (codeInteger == 200) {
String dataString;
try {
dataString = jsonObject.getString("data");
if ((dataString.equals("")) || (dataString.equals("null"))) {
filePathnameList.clear();
detailedFileListMap.clear();
return true;
}
JSONArray dataJsonArray = new JSONArray(dataString);
@@ -563,10 +578,23 @@ public class MyCloudFileController {
fileCacheJsonObject = new JSONObject(fileCacheString);
String filename = fileCacheJsonObject.getString("filename");
String type = fileCacheJsonObject.getString("type");
if (foldername.charAt(foldername.length() - 1) == '/') {
filePathnameList.add(foldername + filename + "@" + type);
} else {
filePathnameList.add(foldername + '/' + filename + "@" + type);
Long time=fileCacheJsonObject.getLong("time");
Long size=fileCacheJsonObject.getLong("size");
if (foldername.charAt(foldername.length() - 1) != '/'){
foldername=foldername+"/";
}
if(type.equals("f")){
// filePathnameList
String fileId=foldername + filename + "@" + type;
filePathnameList.add(fileId);
// map
SingleFile singleFile=new SingleFile(fileId);
singleFile.setFilepath(foldername);
singleFile.setFilename(filename);
singleFile.setType(type);
singleFile.setSize(size);
singleFile.setTime(time);
detailedFileListMap.put(fileId,singleFile);
}
}
return true;
@@ -575,10 +603,108 @@ public class MyCloudFileController {
e.printStackTrace();
return false;
}
}else if(codeInteger==201){
System.out.println("lsFolder: 201大数据传输接口");
String dataString;
try {
dataString = jsonObject.getString("data");
if (dataString.equals("")) {
//数据为空
} else {
JSONObject dataJsonObject = new JSONObject(dataString);
String dataIdString = dataJsonObject.getString("dataId");
Integer dataSizeInteger = dataJsonObject.getInt("dataSize");
Integer sliceNumInteger = dataJsonObject.getInt("sliceNum");
Integer sliceSizeInteger = dataJsonObject.getInt("sliceSize");
byte[] noticelistByte = new byte[dataSizeInteger];
for (Integer sliceNo = 0; sliceNo < sliceNumInteger; sliceNo++) {
// 发送数据请求
Long seqLongT = mainApp.getNewDataReqId();
orderInfo.setSeq(seqLongT);
System.out.println("getDataSlice: " + getGetDataSlice(dataIdString, sliceNo));
orderInfo.setJsonString(getGetDataSlice(dataIdString, sliceNo));
mainApp.minoaDataAPI.executeOrder("/getDataSlice", orderInfo);
// 获取用户列表信息
ResponseData responseDataCache = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLongT);
byte[] byteCache = responseDataCache.getFileSlice();
System.out.println("byteCache size:" + byteCache.length);
System.out.println("byteCache:" + byteCache);
if (sliceNo == (sliceNumInteger - 1)) {
for (int x = (sliceNo * sliceSizeInteger); x < dataSizeInteger; x++) {
noticelistByte[x] = byteCache[x - (sliceNo * sliceSizeInteger)];
}
} else {
for (int x = (sliceNo * sliceSizeInteger); x < (sliceNo * sliceSizeInteger + 7000); x++) {
noticelistByte[x] = byteCache[x - (sliceNo * sliceSizeInteger)];
}
}
}
try {
String cacheString = new String(noticelistByte, "UTF-8");
System.out.println(cacheString);
JSONArray dataJsonArray = new JSONArray(cacheString);
String fileCacheString;
JSONObject fileCacheJsonObject;
// 遍历每个文件信息
for (int i = 0; i < dataJsonArray.length(); i++) {
fileCacheString = dataJsonArray.getString(i);
fileCacheJsonObject = new JSONObject(fileCacheString);
String filename = fileCacheJsonObject.getString("filename");
String type = fileCacheJsonObject.getString("type");
Long time=fileCacheJsonObject.getLong("time");
Long size=fileCacheJsonObject.getLong("size");
if (foldername.charAt(foldername.length() - 1) != '/'){
foldername=foldername+"/";
}
// if(type.equals("f")){
// filePathnameList
String fileId=foldername + filename + "@" + type;
filePathnameList.add(fileId);
// map
SingleFile singleFile=new SingleFile(fileId);
singleFile.setFilepath(foldername);
singleFile.setFilename(filename);
singleFile.setType(type);
singleFile.setSize(size);
singleFile.setTime(time);
detailedFileListMap.put(fileId,singleFile);
// }
}
return true;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
public String getGetDataSlice(String dataId, Integer sliceNo) {
JSONObject jsonObject = new JSONObject();
String commandString = "/getDataSlice";
String usernameString = mainApp.loginer.getUserName();
String uuidString = mainApp.loginer.getUuid();
Integer sliceNoInteger = sliceNo;
String dataIdString = dataId;
try {
jsonObject.put("command", commandString);
jsonObject.put("username", usernameString);
jsonObject.put("uuid", uuidString);
jsonObject.put("dataId", dataIdString);
jsonObject.put("sliceNo", sliceNoInteger);
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception: " + e.getMessage());
}
return jsonObject.toString();
}
// 获取上传文件的json格式
private String getUploadFile(String filename, Integer offset) {
JSONObject jsonObject = new JSONObject();
@@ -600,65 +726,6 @@ public class MyCloudFileController {
return jsonObject.toString();
}
// //上传文件操作=>此函数只支持上传指定文件到用户根目录
// public void sendFileToServer(File file) {
// // 获取要上传文件的文件长度,计算上传次数
// long filelen = file.length();
// int cycle = (int) filelen / mainApp.sliceSize;
// System.out.println("file-len: " + filelen);
// System.out.println("cycle: " + cycle);
// // 发送上传命令给上传接口,接口自行取本地数据
// int flagSuccess = 0; // 记录收到200回复的次数
// for (int i = 0; i <= cycle; i++) {
// OrderInfo orderInfo = new OrderInfo();
// ResponseData responseData = new ResponseData();
// Long seqLong = mainApp.getNewDataReqId();
// orderInfo.setSeq(seqLong);
// // 此时传入的文件路径是windows下的绝对路径
// orderInfo.setJsonString(getUploadFile(file.getAbsolutePath(), i * mainApp.sliceSize));
//
// mainApp.minoaDataAPI.executeOrder("/uploadFile", orderInfo);
// responseData = mainApp.minoaDataAPI.dataCacheQueue.getResponseDataBySeq(seqLong);
//// System.out.println("上传文件的数据回执(200表示成功)"+responseData.getResponseJsonDataString());
// JSONObject jsonObject = responseData.praseRequestData();
// responseData.printSelf();
// // 解析数据
// Integer codeInteger = null;
// try {
// codeInteger = jsonObject.getInt("code");
// } catch (JSONException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// if (codeInteger == 200) {
// flagSuccess++;
// }
// }
// // 每个分片都上传成功
// if (flagSuccess == (cycle + 1)) {
//// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
// Alert alert = new Alert(AlertType.INFORMATION);
// alert.setTitle("上传成功");
// alert.setHeaderText("上传文件成功");
// alert.setContentText("您的文件已上传。");
// alert.showAndWait();
// // 根据当前路径,重新加载整个界面,来刷新listview
// try {
// mainApp.reloadCloudFileOverview(currentPath);
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// } else {
//// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
// Alert alert = new Alert(AlertType.WARNING);
// alert.setTitle("上传失败");
// alert.setHeaderText("上传文件失败");
// alert.setContentText("由于未知原因,您的文件上传失败,非常抱歉。");
// alert.showAndWait();
// }
// }
// 从paneId中获取文件所在路径
public String getPathFromPaneId(String paneId) {
// 标记最后一个/的下标
@@ -731,146 +798,279 @@ public class MyCloudFileController {
}
return false;
}
}
class FileListItem {
// 外部pane
private Pane pane;
private Integer paneWidth;
private Integer paneHeight;
// 头像
private Button head;
private Integer headLength;
// 文本区域
// public TextArea text;
private Text text;
// private Integer textWidth;
// private Integer textHeight;
class FileListItem {
// 外部pane
private Pane pane;
private Integer paneWidth;
private Integer paneHeight;
// 头像
private Button head;
private Integer headLength;
// 文本区域:文件名
private Text text;
// 文件大小
private Text filesizeText;
// 文件创建时间
private Text filetimeText;
// 每个Pane代映射了一个文件[路径+文件名+@文件类型]
String pathfilename;
// 每个Pane代映射了一个文件[路径+文件名+@文件类型]
String pathfilename;
// 组件位置属性
private Integer headXInteger;
private Integer headYInteger;
private Integer textXInteger;
private Integer textYInteger;
// 组件位置属性
private Integer headXInteger;
private Integer headYInteger;
private Integer textXInteger;
private Integer textYInteger;
private Integer fileszTextXInteger;
private Integer fileszTextYInteger;
private Integer filetimeTextXInteger;
private Integer filetimeTextYInteger;
// 设置联系人头像
private void setHeadPortrait(Button button, String filetype) {
button.setStyle(
String.format("-fx-background-image: url('file:resources/images/myFileIcon/%s.png')", filetype));
}
// 设置联系人头像
private void setHeadPortrait(Button button, String filetype) {
button.setStyle(
String.format("-fx-background-image: url('file:resources/images/myFileIcon/%s.png')", filetype));
}
// 构造函数
public FileListItem(String pathfiletypename) {
// 映射数据
this.pathfilename = pathfiletypename;
// 大小配置
paneWidth = 200;
paneHeight = 50;
headLength = 35;
// textWidth = 150;
// textHeight = 25;
// 位置配置
headXInteger = 10;
headYInteger = 10;
textXInteger = 70;
textYInteger = 28;
// 构造函数
public FileListItem(String pathfiletypename) {
// 映射数据
this.pathfilename = pathfiletypename;
// 大小配置
paneWidth = 200;
paneHeight = 50;
headLength = 35;
// 位置配置
headXInteger = 10;
headYInteger = 10;
textXInteger = 70;
textYInteger = 28;
fileszTextXInteger=textXInteger+150;
fileszTextYInteger=textYInteger;
filetimeTextXInteger=textXInteger+280;
filetimeTextYInteger=textYInteger;
pane = new Pane();
head = new Button();
text = new Text();
pane = new Pane();
head = new Button();
text = new Text();
filesizeText=new Text();
filetimeText=new Text();
// 最外面的pane的大小
pane.setPrefSize(paneWidth, paneHeight);
// 最外面的pane的大小
pane.setPrefSize(paneWidth, paneHeight);
// 设置头像和pane的CSS的样式标识
head.getStyleClass().add("head");
pane.getStyleClass().add("pane");
// 设置头像和pane的CSS的样式标识
head.getStyleClass().add("head");
pane.getStyleClass().add("pane");
// 设置消息头像和消息文本属性
head.setPrefSize(headLength, headLength);
// text.setPrefSize(textWidth, textHeight);
// text.setWrapText(true);
// text.setEditable(false);
}
// 设置消息头像和消息文本属性
head.setPrefSize(headLength, headLength);
}
public FileListItem(String pathfilename, String filetype) {
// 映射数据
this.pathfilename = pathfilename + "@" + filetype;
// 大小配
paneWidth = 200;
paneHeight = 50;
headLength = 35;
// textWidth = 150;
// textHeight = 25;
// 位置配置
headXInteger = 10;
headYInteger = 10;
textXInteger = 70;
textYInteger = 28;
pane = new Pane();
head = new Button();
text = new Text();
// 最外面的pane的大小
pane.setPrefSize(paneWidth, paneHeight);
// 设置头像和pane的CSS的样式标识
head.getStyleClass().add("head");
pane.getStyleClass().add("pane");
// 设置消息头像和消息文本属性
head.setPrefSize(headLength, headLength);
// text.setPrefSize(textWidth, textHeight);
// text.setWrapText(true);
// text.setEditable(false);
}
// 根据person获取pane
public Pane getPaneItem() {
String name = this.pathfilename;
// 头像位置
head.setLayoutY(headYInteger);
head.setLayoutX(headXInteger);
// text位置
text.setLayoutX(textXInteger);
text.setLayoutY(textYInteger);
// 头像和气泡文本内容
text.setText(getPureFilenameFromPaneId(name));
// text.setText(name);
setHeadPortrait(head, getFileTypeFromPaneId(name));
pane.getChildren().add(head);
pane.getChildren().add(text);
// 设置pane的id
pane.setId(name);
return pane;
}
// 根据包含路径的文件名获取纯文件名
private String getPureFilenameFromPaneId(String paneId) {
// 标记最后一个/的下标
int indexLeft = -1;
// 标记最后一个@的下标
int indexRight = -1;
for (int i = 0; i < paneId.length(); i++) {
if (paneId.charAt(i) == '@') {
indexRight = i;
} else if (paneId.charAt(i) == '/') {
indexLeft = i;
// 根据person获取pane
public Pane getPaneItem() {
String name = this.pathfilename;
// 头像位
head.setLayoutY(headYInteger);
head.setLayoutX(headXInteger);
// text位置
text.setLayoutX(textXInteger);
text.setLayoutY(textYInteger);
filesizeText.setLayoutX(fileszTextXInteger);
filesizeText.setLayoutY(fileszTextYInteger);
filetimeText.setLayoutX(filetimeTextXInteger);
filetimeText.setLayoutY(filetimeTextYInteger);
// 头像和气泡文本内容
String thisfilename=getPureFilenameFromPaneId(name);
if(StringByteLengthUtil.getByteLength(thisfilename)>20){
thisfilename=thisfilename.substring(0,10)+" ...";
}
text.setText(thisfilename);
setHeadPortrait(head, getFileTypeFromPaneId(name));
// 文件大小
Long size=detailedFileListMap.get(name).getSize();
filesizeText.setText(FileUtil.sizeToShowSize(size));
// 文件创建时间
Long time=detailedFileListMap.get(name).getTime();
filetimeText.setText(FileUtil.timeToDateString(time));
// 文件大小和文件创建时间
pane.getChildren().add(head);
pane.getChildren().add(text);
pane.getChildren().add(filesizeText);
pane.getChildren().add(filetimeText);
// 设置pane的id
pane.setId(name);
return pane;
}
if ((indexLeft == -1) || (indexRight == -1)) {
System.out.println("prase paneId error: " + paneId);
return "";
}
return paneId.substring(indexLeft + 1, indexRight);
}
// 从paneId中获取文件类型
private String getFileTypeFromPaneId(String paneId) {
return paneId.substring(paneId.length() - 1, paneId.length());
// 根据包含路径的文件名获取文件
private String getPureFilenameFromPaneId(String paneId) {
// 标记最后一个/的下标
int indexLeft = -1;
// 标记最后一个@的下标
int indexRight = -1;
for (int i = 0; i < paneId.length(); i++) {
if (paneId.charAt(i) == '@') {
indexRight = i;
} else if (paneId.charAt(i) == '/') {
indexLeft = i;
}
}
if ((indexLeft == -1) || (indexRight == -1)) {
System.out.println("prase paneId error: " + paneId);
return "";
}
return paneId.substring(indexLeft + 1, indexRight);
}
// 从paneId中获取文件类型
private String getFileTypeFromPaneId(String paneId) {
return paneId.substring(paneId.length() - 1, paneId.length());
}
}
}
//class FileListItem {
// // 外部pane
// private Pane pane;
// private Integer paneWidth;
// private Integer paneHeight;
// // 头像
// private Button head;
// private Integer headLength;
// // 文本区域
//// public TextArea text;
// private Text text;
//// private Integer textWidth;
//// private Integer textHeight;
//
// // 每个Pane代映射了一个文件[路径+文件名+@文件类型]
// String pathfilename;
//
// // 组件位置属性
// private Integer headXInteger;
// private Integer headYInteger;
// private Integer textXInteger;
// private Integer textYInteger;
//
// // 设置联系人头像
// private void setHeadPortrait(Button button, String filetype) {
// button.setStyle(
// String.format("-fx-background-image: url('file:resources/images/myFileIcon/%s.png')", filetype));
// }
//
// // 构造函数
// public FileListItem(String pathfiletypename) {
// // 映射数据
// this.pathfilename = pathfiletypename;
// // 大小配置
// paneWidth = 200;
// paneHeight = 50;
// headLength = 35;
//// textWidth = 150;
//// textHeight = 25;
// // 位置配置
// headXInteger = 10;
// headYInteger = 10;
// textXInteger = 70;
// textYInteger = 28;
//
// pane = new Pane();
// head = new Button();
// text = new Text();
//
// // 最外面的pane的大小
// pane.setPrefSize(paneWidth, paneHeight);
//
// // 设置头像和pane的CSS的样式标识
// head.getStyleClass().add("head");
// pane.getStyleClass().add("pane");
//
// // 设置消息头像和消息文本属性
// head.setPrefSize(headLength, headLength);
//// text.setPrefSize(textWidth, textHeight);
//// text.setWrapText(true);
//// text.setEditable(false);
// }
//
// public FileListItem(String pathfilename, String filetype) {
// // 映射数据
// this.pathfilename = pathfilename + "@" + filetype;
// // 大小配置
// paneWidth = 200;
// paneHeight = 50;
// headLength = 35;
//// textWidth = 150;
//// textHeight = 25;
// // 位置配置
// headXInteger = 10;
// headYInteger = 10;
// textXInteger = 70;
// textYInteger = 28;
//
// pane = new Pane();
// head = new Button();
// text = new Text();
//
// // 最外面的pane的大小
// pane.setPrefSize(paneWidth, paneHeight);
//
// // 设置头像和pane的CSS的样式标识
// head.getStyleClass().add("head");
// pane.getStyleClass().add("pane");
//
// // 设置消息头像和消息文本属性
// head.setPrefSize(headLength, headLength);
//// text.setPrefSize(textWidth, textHeight);
//// text.setWrapText(true);
//// text.setEditable(false);
// }
//
// // 根据person获取pane
// public Pane getPaneItem() {
// String name = this.pathfilename;
// // 头像位置
// head.setLayoutY(headYInteger);
// head.setLayoutX(headXInteger);
// // text位置
// text.setLayoutX(textXInteger);
// text.setLayoutY(textYInteger);
// // 头像和气泡文本内容
// text.setText(getPureFilenameFromPaneId(name));
//// text.setText(name);
// setHeadPortrait(head, getFileTypeFromPaneId(name));
// pane.getChildren().add(head);
// pane.getChildren().add(text);
// // 设置pane的id
// pane.setId(name);
// return pane;
// }
//
// // 根据包含路径的文件名获取纯文件名
// private String getPureFilenameFromPaneId(String paneId) {
// // 标记最后一个/的下标
// int indexLeft = -1;
// // 标记最后一个@的下标
// int indexRight = -1;
// for (int i = 0; i < paneId.length(); i++) {
// if (paneId.charAt(i) == '@') {
// indexRight = i;
// } else if (paneId.charAt(i) == '/') {
// indexLeft = i;
// }
// }
// if ((indexLeft == -1) || (indexRight == -1)) {
// System.out.println("prase paneId error: " + paneId);
// return "";
// }
// return paneId.substring(indexLeft + 1, indexRight);
// }
//
// // 从paneId中获取文件类型
// private String getFileTypeFromPaneId(String paneId) {
// return paneId.substring(paneId.length() - 1, paneId.length());
// }
//}
@@ -3,6 +3,7 @@ package cn.minoa.view.mine;
import java.io.File;
import cn.minoa.MainApp;
import cn.minoa.dataRequestInterface.DownLoadClientBasedFacePool;
import cn.minoa.model.Email;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
@@ -124,8 +125,20 @@ public class SingleEmailDetailsController {
}
System.out.println("开始下载... :"+pathfilename);
int flag=mainApp.downloadFileByPathfilename(pathfilename,localDirString);
if(flag==0) {
// int flag=mainApp.downloadFileByPathfilename(pathfilename,localDirString);
Long filelen= mainApp.getServerFileByteLength(pathfilename);
Integer sliceNum = (int)(filelen / mainApp.sliceSize);
if (filelen % mainApp.sliceSize != 0) {
sliceNum++;
}
Long startTime = System.currentTimeMillis();
DownLoadClientBasedFacePool downLoadClient = new DownLoadClientBasedFacePool(pathfilename,
localDirString,sliceNum,mainApp.threadNumberForFileTransfer);
// 下载文件
boolean res = downLoadClient.downloadData();
Long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - startTime) + "ms");
if(res) {
// 弹窗参考:https://code.makery.ch/blog/javafx-dialogs-official/
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("下载成功");
@@ -274,8 +274,8 @@ public class WrittenEmailController {
String pathfilename=emailFilesList.get(i);
//上传该文件到服务器共享文件夹目录下
File file=new File(pathfilename);
Integer res=mainApp.uploadFileToServerSharedFolder(file);
if(res<0){
boolean res=mainApp.uploadFileToServerSharedFolder(file);
if(!res){
flag=false;
}
//将该文件信息[服务器文件路径地址]写入邮件信息中