前后端上传图片(上传发票并获取发票信息)
React+Antd上传图片
上传图片upload组件
<Upload
fileList={this.state.fileListInvoice}
beforeUpload={this.beforeUploadInvoice}
onChange={this.onChangeInvoice}
onRemove={this.handleRemove}
showUploadList={true}
accept=".jpg,.pdf,.jpeg,.bmp,.png"> //允许上传图片的格式
<Button>
<Icon type="upload" /> 上传发票
</Button>
</Upload>
上传图片函数:
onChangeInvoice=(info)=>{ //上传文件改变时的状态
this. setState({fileListInvoice:[{...info.file,status:"done"}] })
}
handleChangeInvoice = (info) =>{
const formData = new FormData();
formData.append('file', info); // 最新上传的文件 转换成FormData , 文件上传有关的传参 都要转换城FormData
formData.append('uName', this.state.uName); // 最新上传的文件 转换成FormData , 文件上传有关的传参 都要转换城FormData
formData.append('type','发票')
const { dispatch } = this.props;
dispatch({
type:'register/fetchUpload',
payload: formData,
}).then((res)=>{ //res图片路径
let map = {
photo:res,
}
axios.post(`${CONNECT_URL}examine/provingInvoice`,qs.stringify(map))//参数1:后端访问路径;参数2:qs将传参转化为json格式
.then((response)=>{
const data = response.data; //返回的信息,此案例上传的为发票,并且使用api获取到了发票的基本信息
if(data.error_msg === 'target detect error'){
message.error('上传图片错误')
}else if(response.data.words_result.Remarks){
message.success('验证成功')
const startPrice = data.words_result.TotalAmount //获取购买价格
this.setState({startPrice:startPrice})
const date = moment(data.words_result.Remarks.split('期')[1]).format('YYYY-MM-DD'); //获取购买时间
this.setState({date:date})
let buytime = moment(date).format("YYYY"); //购买日期年份
let newdate = moment(new Date()).format("YYYY");//当前年份
const i = newdate-buytime; //计算时间差值
}).catch();
})
}
beforeUploadInvoice=file=>{
const isLt10M = file.size / 1024 /1024 < 10;
if (!isLt10M) {
message.error('Image must smaller than 10MB!');
return false;
}else{
this.handleChangeInvoice(file);
return true;
}
};
其中两次访问后台
1.访问后台将图片上传到本地,并返回本地发票的路径:
1.1 handleChangeInvoice函数通过dva框架的dispatch
dispatch({
type:'register/fetchUpload', //register:momodels文件的regi.js文件中的fetchUpload方法
payload: formData,//向fetchUpload方法传参,formData包含图片信息
}).then((res)=>{ //返回数据
}
1.2register文件的fetchUpload方法
effects: {
*fetchUpload({ payload }, { call }) {
const response = yield call(uploadFile, payload);//调用service文件里的uploadFile方法,payload为参数
return response; //从后端返回的数据
},
},
1.2.1前提是需要导入uploadFile方法
import {
uploadFile, //方法名
} from '../services/user'; //含有此方法的文件路径
1.3 service文件夹
// 文件上传
export async function uploadFile(payload) {
return request(`http://localhost:8088/q/w`,{
method:'POST',
body:payload,
})
};
后端SpringBoot接收图片
接收图片
public String test(@RequestParam("file") MultipartFile file , HttpServletResponse response, HttpServletRequest request,@RequestParam("uName") String uName,@RequestParam("type") String type) throws IOException {
// uploads文件夹位置
String rootPath = request.getSession().getServletContext().getRealPath("/");
// 原始名称
String originalFileName = file.getOriginalFilename();
// 创建文件夹
File dateDirs = new File("E:\\Work\\second_hand\\public\\icons");
File dateDirsAdmin = new File("E:\\Work\\JavaGit\\react\\public\\icons");
// 新文件
File newFile = new File( dateDirs + "\\"+ originalFileName);
File newFileAdmin = new File( dateDirsAdmin + "\\"+ originalFileName);
// 判断目标文件所在目录是否存在
if( !newFile.getParentFile().exists()) { //判断文件夹是否存在
// 如果目标文件所在的目录不存在,则创建父目录
newFile.getParentFile().mkdirs();
}/*else if(!newFile.exists()){ //判断文件(图片)是否存在
}else{
System.out.println( "该文件已存在!");
return "该文件已存在!";
}*/
// 判断目标文件所在目录是否存在
if( !newFileAdmin.getParentFile().exists()) { //判断文件夹是否存在
// 如果目标文件所在的目录不存在,则创建父目录
newFileAdmin.getParentFile().mkdirs();
}/*else if(!newFileAdmin.exists()){ //判断文件(图片)是否存在
}else{
System.out.println( "该文件已存在!");
return "该文件已存在!";
}*/
// 将内存中的数据写入磁盘
file.transferTo(newFile);
// 将内存中的数据写入磁盘
copy(originalFileName, "E:\\Work\\second_hand\\public\\icons", "E:\\Work\\JavaGit\\react\\public\\icons");
// 完整的url
String fileUrl = dateDirs + "\\" + originalFileName;
if(type.equals("发票")){
return fileUrl;
}
System.out.println(fileUrl);
String Url = "/icons" + "/" + originalFileName;
System.out.println(Url);
return Url;
}
private static void copy(String filename, String oldpath, String newpath) throws IOException {
// TODO Auto-generated method stub
File oldpaths = new File(oldpath + "/" + filename);
File newpaths = new File(newpath + "/" + filename);
if (!newpaths.exists()) {
Files.copy(oldpaths.toPath(), newpaths.toPath());
} else {
newpaths.delete();
Files.copy(oldpaths.toPath(), newpaths.toPath());
}
}
SpringBoot后端解析发票信息
//7.验证发票
@RequestMapping("/provingInvoice")
public Object provingInvoice(@RequestParam Map map){
String path = map.get("photo").toString();
return Invoice.invoice(path);
}
public class Invoice {
@Autowired
private AuthService authService;
/**
* 重要提示代码中所需工具类
* FileUtil,Base64Util,HttpUtil,GsonUtils请从
* https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
* https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
* https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
* https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
* 下载
*/
public static String invoice(String path) {
// 请求url
/*String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/invoice";*/
String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/vat_invoice"; //增值税发票识别URL
try {
// 本地文件路径
String filePath = path;
byte[] imgData = FileUtil.readFileByBytes(filePath);
String imgStr = Base64Util.encode(imgData);
String imgParam = URLEncoder.encode(imgStr, "UTF-8");
String param = "image=" + imgParam;
// 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
String accessToken = AuthService.getAuth();
String result = HttpUtil.post(url, accessToken, param);
System.out.println(result);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/* public static void main(String[] args) {
Invoice.invoice();
}*/
}
<!--百度api-->
<!-- https://mvnrepository.com/artifact/com.baidu.aip/java-sdk -->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.12.0</version>
</dependency>