|
|
|
@ -6,6 +6,10 @@ import com.cjy.back.ybsjAppointment.entity.vo.ReservationNowVO; |
|
|
|
|
import com.cjy.back.ybsjAppointment.service.YbsjyAppointmentRecordService; |
|
|
|
|
import com.cjy.back.ybsjAppointment.service.YbsjyAppointmentSettingService; |
|
|
|
|
import com.cjy.util.ServerResponse; |
|
|
|
|
import org.apache.commons.fileupload.FileItem; |
|
|
|
|
import org.apache.commons.fileupload.FileItemFactory; |
|
|
|
|
import org.apache.commons.fileupload.disk.DiskFileItemFactory; |
|
|
|
|
import org.apache.commons.io.FileUtils; |
|
|
|
|
import org.json.JSONArray; |
|
|
|
|
import org.json.JSONObject; |
|
|
|
|
import org.junit.jupiter.api.extension.MediaType; |
|
|
|
@ -16,17 +20,18 @@ import org.springframework.web.bind.annotation.RequestMapping; |
|
|
|
|
import org.springframework.web.bind.annotation.RequestParam; |
|
|
|
|
import org.springframework.web.bind.annotation.RestController; |
|
|
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
|
|
import org.springframework.web.multipart.commons.CommonsMultipartFile; |
|
|
|
|
import sun.net.www.http.HttpClient; |
|
|
|
|
|
|
|
|
|
import java.io.OutputStream; |
|
|
|
|
import java.io.*; |
|
|
|
|
import java.net.HttpURLConnection; |
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
|
|
|
import java.io.BufferedReader; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.io.InputStreamReader; |
|
|
|
|
import java.net.URL; |
|
|
|
|
import java.net.URLConnection; |
|
|
|
|
import java.util.UUID; |
|
|
|
|
import java.util.regex.Matcher; |
|
|
|
|
import java.util.regex.Pattern; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @author liangjiawei |
|
|
|
@ -180,63 +185,176 @@ public class YbsjyAppletsAppointmentController { |
|
|
|
|
return ServerResponse.createBySuccess(response); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// public static String uploadImage(String accessToken, File imageFile) throws IOException {
|
|
|
|
|
// String url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=" + accessToken + "&type=image";
|
|
|
|
|
// OkHttpClient client = new OkHttpClient();
|
|
|
|
|
// RequestBody body = new MultipartBody.Builder()
|
|
|
|
|
// .setType(MultipartBody.FORM)
|
|
|
|
|
// .addFormDataPart("media", imageFile.getName(),
|
|
|
|
|
// RequestBody.create(imageFile, MediaType.parse("image/*")))
|
|
|
|
|
// .build();
|
|
|
|
|
// Request request = new Request.Builder().url(url).post(body).build();
|
|
|
|
|
// try (Response response = client.newCall(request).execute()) {
|
|
|
|
|
// JSONObject result = new JSONObject(response.body().string());
|
|
|
|
|
// return result.getString("media_id"); // 返回永久素材ID
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
@RequestMapping("/createDraft") |
|
|
|
|
public ServerResponse createDraft(String accessToken, String title, String content, String thumbMediaId) throws IOException { |
|
|
|
|
String url = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=" + accessToken; |
|
|
|
|
|
|
|
|
|
// 构建请求体
|
|
|
|
|
JSONObject article = new JSONObject(); |
|
|
|
|
article.put("title", title); |
|
|
|
|
article.put("content", content); |
|
|
|
|
article.put("thumb_media_id", thumbMediaId); |
|
|
|
|
article.put("need_open_comment", 0); |
|
|
|
|
|
|
|
|
|
JSONArray articles = new JSONArray(); |
|
|
|
|
articles.put(article); |
|
|
|
|
JSONObject requestBody = new JSONObject().put("articles", articles); |
|
|
|
|
|
|
|
|
|
// 创建连接
|
|
|
|
|
// 1. 下载网络图片(支持自动重试)
|
|
|
|
|
private static File downloadImage(String imageUrl) throws IOException, InterruptedException { |
|
|
|
|
File tempFile = File.createTempFile("wx_", ".tmp"); // 先创建临时文件
|
|
|
|
|
|
|
|
|
|
// 下载文件内容
|
|
|
|
|
FileUtils.copyURLToFile(new URL(imageUrl), tempFile); |
|
|
|
|
|
|
|
|
|
// 验证文件头
|
|
|
|
|
try (InputStream is = new FileInputStream(tempFile)) { |
|
|
|
|
byte[] header = new byte[8]; |
|
|
|
|
is.read(header); |
|
|
|
|
|
|
|
|
|
// PNG头: 89 50 4E 47 0D 0A 1A 0A
|
|
|
|
|
// JPEG头: FF D8 FF
|
|
|
|
|
if (!(header[0] == (byte) 0x89 && header[1] == 'P' && header[2] == 'N' && header[3] == 'G') && |
|
|
|
|
!(header[0] == (byte) 0xFF && header[1] == (byte) 0xD8 && header[2] == (byte) 0xFF)) { |
|
|
|
|
throw new IOException("无效的图片格式"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return tempFile; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 2. 微信图片上传(修复41005错误)
|
|
|
|
|
private static String uploadToWeChat(String accessToken, File file) throws IOException { |
|
|
|
|
String newName =""; |
|
|
|
|
// 1. 验证文件类型
|
|
|
|
|
String fileName = file.getName().toLowerCase(); |
|
|
|
|
if (!fileName.endsWith(".jpg") && !fileName.endsWith(".jpeg") && !fileName.endsWith(".png")) { |
|
|
|
|
// 重命名临时文件为有效扩展名
|
|
|
|
|
newName = fileName.split("\\.")[0] + ".jpg"; |
|
|
|
|
File newFile = new File(file.getParent(), newName); |
|
|
|
|
file.renameTo(newFile); |
|
|
|
|
file = newFile; |
|
|
|
|
} |
|
|
|
|
FileInputStream input = new FileInputStream(file); |
|
|
|
|
String url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=" + accessToken + "&type=image"; |
|
|
|
|
|
|
|
|
|
String boundary = "----WebKitFormBoundary" + System.currentTimeMillis(); |
|
|
|
|
String lineEnd = "\r\n"; |
|
|
|
|
String twoHyphens = "--"; |
|
|
|
|
|
|
|
|
|
HttpURLConnection connection = null; |
|
|
|
|
try { |
|
|
|
|
URL requestUrl = new URL(url); |
|
|
|
|
connection = (HttpURLConnection) requestUrl.openConnection(); |
|
|
|
|
connection.setDoOutput(true); |
|
|
|
|
connection.setDoInput(true); |
|
|
|
|
connection.setUseCaches(false); |
|
|
|
|
connection.setRequestMethod("POST"); |
|
|
|
|
connection.setRequestProperty("Connection", "Keep-Alive"); |
|
|
|
|
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); |
|
|
|
|
|
|
|
|
|
OutputStream outputStream = connection.getOutputStream(); |
|
|
|
|
PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"), true); |
|
|
|
|
|
|
|
|
|
// 添加文件部分
|
|
|
|
|
writer.append(twoHyphens + boundary + lineEnd); |
|
|
|
|
writer.append("Content-Disposition: form-data; name=\"media\"; filename=\"" + newName + "\"" + lineEnd); |
|
|
|
|
writer.append("Content-Type: image/*" + lineEnd); |
|
|
|
|
writer.append(lineEnd); |
|
|
|
|
writer.flush(); |
|
|
|
|
|
|
|
|
|
// 写入文件内容(使用 MultipartFile.getInputStream())
|
|
|
|
|
InputStream inputStream = input; // 关键修改点!
|
|
|
|
|
byte[] buffer = new byte[4096]; |
|
|
|
|
int bytesRead; |
|
|
|
|
while ((bytesRead = inputStream.read(buffer)) != -1) { |
|
|
|
|
outputStream.write(buffer, 0, bytesRead); |
|
|
|
|
} |
|
|
|
|
outputStream.flush(); |
|
|
|
|
inputStream.close(); |
|
|
|
|
|
|
|
|
|
// 结束部分
|
|
|
|
|
writer.append(lineEnd); |
|
|
|
|
writer.append(twoHyphens + boundary + twoHyphens + lineEnd); |
|
|
|
|
writer.close(); |
|
|
|
|
|
|
|
|
|
// 获取响应
|
|
|
|
|
int responseCode = connection.getResponseCode(); |
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) { |
|
|
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); |
|
|
|
|
StringBuilder response = new StringBuilder(); |
|
|
|
|
String line; |
|
|
|
|
while ((line = reader.readLine()) != null) { |
|
|
|
|
response.append(line); |
|
|
|
|
} |
|
|
|
|
reader.close(); |
|
|
|
|
|
|
|
|
|
JSONObject result = new JSONObject(response.toString()); |
|
|
|
|
return result.getString("url"); |
|
|
|
|
} else { |
|
|
|
|
throw new IOException("Server returned non-OK status: " + responseCode); |
|
|
|
|
} |
|
|
|
|
} finally { |
|
|
|
|
if (connection != null) { |
|
|
|
|
connection.disconnect(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 替换内容中的图片链接
|
|
|
|
|
private static String processContent(String html, String accessToken) throws Exception { |
|
|
|
|
Pattern pattern = Pattern.compile("<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>"); |
|
|
|
|
Matcher matcher = pattern.matcher(html); |
|
|
|
|
StringBuffer result = new StringBuffer(); |
|
|
|
|
|
|
|
|
|
while (matcher.find()) { |
|
|
|
|
String imgUrl = matcher.group(1); |
|
|
|
|
File tempFile = downloadImage(imgUrl); |
|
|
|
|
String wechatUrl = uploadToWeChat(accessToken, tempFile); |
|
|
|
|
matcher.appendReplacement(result, "<img src='" + wechatUrl + "'/>"); |
|
|
|
|
tempFile.delete(); |
|
|
|
|
} |
|
|
|
|
matcher.appendTail(result); |
|
|
|
|
return result.toString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4. 创建草稿
|
|
|
|
|
private static void createDraft(String accessToken, String title, String content) throws IOException { |
|
|
|
|
String url = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=" + accessToken; |
|
|
|
|
|
|
|
|
|
JSONObject article = new JSONObject() |
|
|
|
|
.put("title", title) |
|
|
|
|
.put("content", content) |
|
|
|
|
.put("thumb_media_id", "qR_BnS7D9o1TqpJLTGV3Pmbnz48dU3zFGu6Y_9ws5iKDXNFBGdIHIyRXJVuIjK1b") |
|
|
|
|
.put("show_cover_pic", 1); |
|
|
|
|
JSONArray articles = new JSONArray().put(article); |
|
|
|
|
String requestBody = new JSONObject().put("articles", articles).toString(); |
|
|
|
|
|
|
|
|
|
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); |
|
|
|
|
conn.setRequestMethod("POST"); |
|
|
|
|
conn.setRequestProperty("Content-Type", "application/json"); |
|
|
|
|
conn.setDoOutput(true); |
|
|
|
|
conn.setRequestProperty("Content-Type", "application/json"); |
|
|
|
|
|
|
|
|
|
// 发送请求
|
|
|
|
|
try (OutputStream os = conn.getOutputStream()) { |
|
|
|
|
os.write(requestBody.toString().getBytes("UTF-8")); |
|
|
|
|
os.write(requestBody.getBytes("UTF-8")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 处理响应
|
|
|
|
|
int responseCode = conn.getResponseCode(); |
|
|
|
|
if (responseCode != HttpURLConnection.HTTP_OK) { |
|
|
|
|
throw new IOException("HTTP error code: " + responseCode); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try (BufferedReader br = new BufferedReader( |
|
|
|
|
new InputStreamReader(conn.getInputStream(), "UTF-8"))) { |
|
|
|
|
StringBuilder response = new StringBuilder(); |
|
|
|
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { |
|
|
|
|
String line; |
|
|
|
|
StringBuilder response = new StringBuilder(); |
|
|
|
|
while ((line = br.readLine()) != null) { |
|
|
|
|
response.append(line); |
|
|
|
|
} |
|
|
|
|
JSONObject result = new JSONObject(response.toString()); |
|
|
|
|
return result.getString("media_id"); |
|
|
|
|
} finally { |
|
|
|
|
conn.disconnect(); |
|
|
|
|
System.out.println("草稿创建结果: " + response); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 完整流程执行
|
|
|
|
|
public static void main(String[] args) { |
|
|
|
|
String accessToken = "91_ylo5YKGyByedvMot_MpRHPR-sECJQR5rJP0AkZUUIxQF4hlmboAj3KHbKu5NhdX-Z4YXMFerlcymRYIuzxczqvrX01iLZHEu1SLRD4Lf7tbuTNIQWN0JXlPJeVEXDRgAHAQWK"; |
|
|
|
|
String originalContent = "<p>测试</p><p><img src=\"https://www.lbgjtoa.com//ueditor/jsp/upload/image/20250410/1744249230410003547.png\" title=\"1744249230410003547.png\" alt=\"zhxh.png\"/></p><p>测试</p><p><img src=\"https://www.lbgjtoa.com//ueditor/jsp/upload/image/20250410/1744249247602088781.png\" title=\"1744249247602088781.png\" alt=\"zhxh.png\"/></p>"; |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
// 步骤1: 处理内容中的图片
|
|
|
|
|
String processedContent = processContent(originalContent, accessToken); |
|
|
|
|
System.out.println("处理后的内容:\n" + processedContent); |
|
|
|
|
|
|
|
|
|
// 步骤2: 创建草稿
|
|
|
|
|
createDraft(accessToken, "测试文章1", processedContent); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
System.err.println("处理失败: " + e.getMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|