1、背景
测试阶段文件上传服务器为测试文件服务器,预览时根据id获取的测试服务器文件。
但发到线上后发现文件上传到了测试服务器,读取文件时又是从线上的文件服务器读取的。因此导致了文件显示异常。
2、数据恢复分析
先从测试环境获取到文件(这些文件实际为关键用户所上传的文件)
(1)后端开发连接备份库,查询到所有相关的日报记录对应的文件id;
(2)通过文件id拼接url下载文件,这里有两种思路
- 通过拼接url,利用浏览器访问接口,浏览器响应为图片文件通过selenium将图片文件保存下来;
- 通过拼接url,跑接口将接口响应的文件流转成文件保存下来;
? ? ? ? ? 因为第一种形式一致需要占用浏览器,这里采用了第二种形式;
(3)将文件上传到生产环境
(4)更新生产环境对应的文件id
3、脚本编码
(1)依赖框架testNG,httpclient
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
</dependencies>
(2)接口分析
如图所示,在直接请求实际在请求时做了两次重定向
第一次重定向,c3951a59182e2bce26df70ce9dbc480ce5e01f75 是个随机字符串,因此无法得到准确的图片路径?
利用postman请求接口响应为图片
这里其实不用太多的关注请求时重定向了多少次,最终都会获取到最终的响应结果。
(3)编码
第一步,建立config.properties配置文件,用于维护请求域名
host = http://localhost
第二步,写一个Common类,用于管理接口请求
package org.example.common;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* @description 管理请求方式
*/
public class Common {
private static ResourceBundle bundle;
private static HttpClient httpClient = new DefaultHttpClient();
public static String getHost(){
bundle = ResourceBundle.getBundle("config", Locale.CHINA);
return bundle.getString("host");
}
/**
* @description Post请求调用
* @param uri
* @param param
* @return
*/
public static String doPost(String uri,String param){
HttpPost post = new HttpPost(uri);
JSONObject jsonObject = JSONObject.parseObject(param);
StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
post.setEntity(entity);
try {
HttpResponse response = httpClient.execute(post);
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(result);
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @return 下载文件
*/
public static String doGet(String uri,String path){
HttpGet get = new HttpGet(uri);
String filename = null;
try {
HttpResponse response = httpClient.execute(get);
// 获取文件名称
Header[] allHeaders = response.getAllHeaders();
for(Header header: allHeaders){
if (header.getValue().toString().contains("filename")){
String[] split = header.getValue().split("\"");
filename = split[1];
}
}
// 将文件流转成文件并保存
HttpEntity entity = response.getEntity();
InputStream in = entity.getContent();
File file = new File(path + filename);
FileOutputStream fout = new FileOutputStream(file);
int l = -1;
byte[] tmp = new byte[1024];
while ((l = in.read(tmp)) != -1) {
fout.write(tmp, 0, l);
}
fout.flush();
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
第三步,写一个类当传GET就调用get请求,传POST就调用post请求
package org.example.utils;
import org.example.common.Common;
import java.lang.reflect.Method;
public class RequestMethod {
/**
* @param request
* @return
* @description 根据输入的请求方式选择调用的是get还是post方法
*/
public static Method getRequest(String request) {
Class clazz = Common.class;
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods){
if (method.getName().contains(request)){
return method;
}
}
return null;
}
}
第四步,调用方法
package org.example.test;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import org.example.common.Common;
import org.example.utils.RequestMethod;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class Picture {
String host = Common.getHost();
String uri = null;
String param = null;
/**
* @description 读取文件中所需要的数据,如上图中的文件id
*/
public static List readExcel(){
String path = "C:\\Users\\Administrator\\Downloads\\dates.xls";
List<String> list = new ArrayList();
InputStream inputStream = null;
try {
inputStream = new FileInputStream(path);
Workbook workbook = Workbook.getWorkbook(inputStream);
Sheet sheet = workbook.getSheet(0);
Cell[] column = sheet.getColumn(6);
for (Cell cell:column){
list.add(cell.getContents().toString());
}
return list;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (BiffException e) {
e.printStackTrace();
}
return null;
}
@Test
public void login() {
try {
uri = host + "/login";
param = "{'username':'username','password':'password'}";
Method post = RequestMethod.getRequest("Post");
String result = (String) post.invoke(Common.class, uri, param);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Assert.assertNotEquals("code","200");
}
/**
* 这里需要登录后才能请求
*/
@Test(dependsOnMethods = {"login"})
public void getPicture(){
try {
// 原url
String url = host+"/file/preview?fileId=";
// 文件路径
String path = "C:\\Users\\Administrator\\Desktop\\download2\\";
// 获取所有id
List<String> list = readExcel();
for (String file_id: list){
String current_url = url + file_id;
// 下载文件
Method get = RequestMethod.getRequest("Get");
// 利用文件id+原文件名重新对文件命名
get.invoke(Common.class, current_url, path+file_id+"_");
Thread.sleep(3000);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
|