test-mobile-avatar-upload.html 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>移动端头像上传测试</title>
  7. <style>
  8. body {
  9. font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  10. margin: 0;
  11. padding: 20px;
  12. background: #f5f5f5;
  13. }
  14. .container {
  15. max-width: 400px;
  16. margin: 0 auto;
  17. background: white;
  18. padding: 20px;
  19. border-radius: 10px;
  20. box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  21. }
  22. .avatar-preview {
  23. width: 100px;
  24. height: 100px;
  25. border-radius: 50%;
  26. background: #ddd;
  27. margin: 20px auto;
  28. display: flex;
  29. align-items: center;
  30. justify-content: center;
  31. overflow: hidden;
  32. }
  33. .avatar-preview img {
  34. width: 100%;
  35. height: 100%;
  36. object-fit: cover;
  37. }
  38. .button {
  39. display: block;
  40. width: 100%;
  41. padding: 12px;
  42. margin: 10px 0;
  43. background: #007bff;
  44. color: white;
  45. border: none;
  46. border-radius: 6px;
  47. font-size: 16px;
  48. cursor: pointer;
  49. }
  50. .button:disabled {
  51. background: #ccc;
  52. cursor: not-allowed;
  53. }
  54. .progress {
  55. margin: 10px 0;
  56. color: #666;
  57. }
  58. .error {
  59. color: #dc3545;
  60. margin: 10px 0;
  61. }
  62. .success {
  63. color: #28a745;
  64. margin: 10px 0;
  65. }
  66. </style>
  67. </head>
  68. <body>
  69. <div class="container">
  70. <h2>移动端头像上传测试</h2>
  71. <div class="avatar-preview" id="avatarPreview">
  72. <span>头像预览</span>
  73. </div>
  74. <input type="file" id="fileInput" accept="image/*" style="display: none;">
  75. <button class="button" onclick="selectFile()">选择头像图片</button>
  76. <button class="button" onclick="testUpload()" id="uploadBtn" disabled>测试上传</button>
  77. <div class="progress" id="progress"></div>
  78. <div class="error" id="error"></div>
  79. <div class="success" id="success"></div>
  80. <button class="button" onclick="testMinioAPI()" style="background: #28a745;">测试Minio API连接</button>
  81. </div>
  82. <script>
  83. let selectedFile = null;
  84. function selectFile() {
  85. document.getElementById('fileInput').click();
  86. }
  87. document.getElementById('fileInput').addEventListener('change', function(e) {
  88. const file = e.target.files[0];
  89. if (file) {
  90. selectedFile = file;
  91. // 显示预览
  92. const reader = new FileReader();
  93. reader.onload = function(e) {
  94. const preview = document.getElementById('avatarPreview');
  95. preview.innerHTML = `<img src="${e.target.result}" alt="预览">`;
  96. };
  97. reader.readAsDataURL(file);
  98. // 启用上传按钮
  99. document.getElementById('uploadBtn').disabled = false;
  100. }
  101. });
  102. async function testUpload() {
  103. if (!selectedFile) {
  104. alert('请先选择文件');
  105. return;
  106. }
  107. const progress = document.getElementById('progress');
  108. const error = document.getElementById('error');
  109. const success = document.getElementById('success');
  110. progress.textContent = '准备上传...';
  111. error.textContent = '';
  112. success.textContent = '';
  113. try {
  114. // 模拟使用minio.ts上传
  115. const formData = new FormData();
  116. formData.append('file', selectedFile);
  117. const response = await fetch('/api/v1/files/upload-policy', {
  118. method: 'POST',
  119. headers: {
  120. 'Content-Type': 'application/json',
  121. },
  122. body: JSON.stringify({
  123. name: selectedFile.name,
  124. type: selectedFile.type,
  125. size: selectedFile.size,
  126. path: `test/avatars/${Date.now()}_${selectedFile.name}`
  127. })
  128. });
  129. if (!response.ok) {
  130. throw new Error('获取上传策略失败');
  131. }
  132. const policy = await response.json();
  133. progress.textContent = '获取策略成功,开始上传...';
  134. // 模拟上传到MinIO
  135. const uploadForm = new FormData();
  136. Object.entries(policy.uploadPolicy).forEach(([key, value]) => {
  137. if (key !== 'key' && key !== 'host' && key !== 'prefix' && typeof value === 'string') {
  138. uploadForm.append(key, value);
  139. }
  140. });
  141. uploadForm.append('key', policy.uploadPolicy.key);
  142. uploadForm.append('file', selectedFile);
  143. const uploadResponse = await fetch(policy.uploadPolicy.host, {
  144. method: 'POST',
  145. body: uploadForm
  146. });
  147. if (!uploadResponse.ok) {
  148. throw new Error('上传失败');
  149. }
  150. const fileUrl = `${policy.uploadPolicy.host}/${policy.uploadPolicy.key}`;
  151. success.textContent = `上传成功!文件URL: ${fileUrl}`;
  152. progress.textContent = '';
  153. } catch (err) {
  154. error.textContent = '上传失败: ' + err.message;
  155. progress.textContent = '';
  156. }
  157. }
  158. async function testMinioAPI() {
  159. const progress = document.getElementById('progress');
  160. const error = document.getElementById('error');
  161. const success = document.getElementById('success');
  162. progress.textContent = '测试API连接...';
  163. error.textContent = '';
  164. success.textContent = '';
  165. try {
  166. const response = await fetch('/api/v1/files/upload-policy', {
  167. method: 'POST',
  168. headers: {
  169. 'Content-Type': 'application/json',
  170. },
  171. body: JSON.stringify({
  172. name: 'test.jpg',
  173. type: 'image/jpeg',
  174. size: 1024,
  175. path: 'test/test.jpg'
  176. })
  177. });
  178. if (response.ok) {
  179. const data = await response.json();
  180. success.textContent = 'API连接正常!';
  181. progress.textContent = '';
  182. } else {
  183. throw new Error('API返回错误: ' + response.status);
  184. }
  185. } catch (err) {
  186. error.textContent = 'API测试失败: ' + err.message;
  187. progress.textContent = '';
  188. }
  189. }
  190. </script>
  191. </body>
  192. </html>