微信公众号开发使用weui上传图片

xiaoxiao2021-03-01  16

先说一下遇到的问题,

1.刚开始在开发阶段直接前台用ajax调接口上传图片没问题,可是到了正式服务器部署时,问题出现了。好像是无法跨域(可能是服务器域名化了的原因),但是后台接口方法中已经添加了允许跨域请求的代码:

//跨域请求 response.setHeader("Access-Control-Allow-Origin", "*");

2.于是,调整方案,前台 ajax 上传文件提交到后台,在后台调用接口来完成文件上传,代码写完测试时又发现问题了,大一点的图片传到后台时接收不到,部分android手机上传的图片后台也接收不到。

最终的解决方案:

前台使用fetch发起请求,并且将图片转换成  base64字符串再提交到后台,后台解析成图片调用接口完成图片上传。

注意:部分Android手机出现点击图片上传按钮无响应的情况,经排查是下面这段代码的问题。

<input class="weui_uploader_input" name="file" type="file" id="up_file" accept="image/jpg,image/jpeg,image/png,image/gif" multiple />  

部分Android手机不支持  H5的multiple  属性,去掉即可(去掉之后在选取图片时一次只能选择一张)

一、前端上传图片:

前端使用 weui 来选取图片。

<div class="weui_uploader z_photo1"> <div class="weui_uploader_bd"> <ul class="weui_uploader_files" id="img2x"> </ul> <div class="weui_uploader_input_wrp"> <input class="weui_uploader_input" name="file" type="file" id="up_file" accept="image/jpg,image/jpeg,image/png,image/gif" multiple /> </div> </div> </div>

js部分,通过fetch将选取到的图片发给后台处理

$(function() { // 允许上传的图片类型 var allowTypes = ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']; // 1024KB*10),也就是 10MB var maxSize = 1024 * 10 * 1024; // 图片最大宽度 var maxWidth = 9000; // 最大上传图片数量 var maxCount = 6; $('#up_file').on('change', function(event) { var files = event.target.files; //console.log(files); //console.log("--files.length--",files.length); // 如果没有选中文件,直接返回 if (files.length === 0) { return; } for (var i = 0, len = files.length; i < len; i++) { var file = files[i]; var reader = new FileReader(); // 如果类型不在允许的类型范围内 if (allowTypes.indexOf(file.type) === -1) { $.weui.alert({ text: '该类型不允许上传' }); continue; } if (file.size > maxSize) { $.weui.alert({ text: '图片太大,不允许上传' }); continue; } if ($('.weui_uploader_file').length >= maxCount) { $.weui.alert({ text: '最多只能上传' + maxCount + '张图片' }); return; } //console.log(file.name); var _canvas; reader.onload = function(e) { //console.log('--render.onload-'); var img = new Image(); img.onload = function() { //console.log('--img.onload-'); // 不要超出最大宽度 var w = Math.min(maxWidth, img.width); // 高度按比例计算 var h = img.height * (w / img.width); var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); // 设置 canvas 的宽度和高度 canvas.width = w; canvas.height = h; ctx.drawImage(img, 0, 0, w, h); var base64 = canvas.toDataURL('image/png'); // 插入到预览区 var progress = 0; function uploading() { } }; var formData = new FormData(); formData.append('file', e.target.result); formData.append('busId', "${pkId}"); formData.append('fileName', file.name); fetch("${ctx}/wechat/eventReport/uploadFile", { method: 'POST', headers: { }, body: formData, }).then((response) = >response.json()).then((responseData) = >{ //console.log(responseData); if (responseData.success) { var imgNames = responseData.data; //这里是将图片上传之后,后台返回的图片的存放路径存到了imgArr数据组// 中,方便前台页面上回显上传的图片。 for (var i = 0; i < imgNames.length; i++) { var image = imgNames[i]; if (image) { imgArr.push(image); } } //这个就是让图片回显在页面上的函数,每个人的处理方式都不一样,就不贴出来了。 refreshImg(); } else { layer.msg('上传失败!', { time: 2000 }); } }). catch((error) = >{ console.error('error', error); layer.msg('上传失败!', { time: 2000 }); }); }; reader.readAsDataURL(file); } }); })

二、后台处理图片

先将base64字符串转为图片。这里使用 restTemplate来请求接口,所以需要将图片文件先转为 FileSystemResource类型,

只能先生成一个 FileSystemResource 类型的文件,上传成功之后在删除即可。

@RequestMapping(value = "/uploadFile",method = RequestMethod.POST) @ResponseBody public Map<String,Object> uploadV(HttpServletRequest request,HttpServletResponse response,String file,String fileName,String busId) { Map<String,Object> map = new HashMap<String,Object>(); List<String> resList = new ArrayList<String>(); try{ //file = file.substring("data:image/png;base64,".length(),file.length()); file = file.substring(file.indexOf("base64,")+7,file.length()); String tempFileName = UUID.randomUUID().toString().replaceAll("-", "")+fileName.substring(fileName.lastIndexOf(".")); //在项目的webapp文件夹下新建一个tempFile文件夹,用来存放生成的临时文件 String tempFilePath = request.getSession().getServletContext().getRealPath("/") +"tempFile/" + tempFileName; Base64Utils.Base64ToImage(file, tempFilePath); FileSystemResource resource = new FileSystemResource(tempFilePath); MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("file", resource); param.add("busId", busId); //Constants.fileUploadUrl 是上传图片的接口的url String string = restTemplate.postForObject(Constants.fileUploadUrl, param, String.class); //System.out.println(string); new File(tempFilePath).delete(); JSONObject json = JSONObject.fromObject(string); if(json.getBoolean("success")){ resList.add(json.getString("data")); } map.put("data", resList); map.put("success", true); } catch(Exception e){ map.put("success", false); e.printStackTrace(); } return map; }

将base64字符串转为图片的工具类:

package *****; import java.io.FileOutputStream; import java.io.OutputStream; import org.hibernate.internal.util.StringHelper; import Decoder.BASE64Decoder; public class Base64Utils { /** * base64字符串转换成图片 * @param imgStr base64字符串 * @param imgFilePath 图片存放路径 * @return * * @author ZHANGJL * @dateTime 2018-02-23 14:42:17 */ public static boolean Base64ToImage(String imgStr,String imgFilePath) { // 对字节数组字符串进行Base64解码并生成图片 if (StringHelper.isEmpty(imgStr)) // 图像数据为空 return false; BASE64Decoder decoder = new BASE64Decoder(); try { // Base64解码 byte[] b = decoder.decodeBuffer(imgStr); for (int i = 0; i < b.length; ++i) { if (b[i] < 0) {// 调整异常数据 b[i] += 256; } } OutputStream out = new FileOutputStream(imgFilePath); out.write(b); out.flush(); out.close(); return true; } catch (Exception e) { return false; } } }

三、后台接口处理上传过来的图片

上传文件接口,这里 List<MultipartFile>  files 中就是接收到的文件了,请自行处理,代码省略了。

@RequestMapping(value = "/hzz/uploadv", method = RequestMethod.POST) @ResponseBody public Object handleFileUploadV(HttpServletRequest request, HttpServletResponse response) { //跨域请求 response.addHeader("Access-Control-Allow-Origin", "*");//http://localhost:8086 List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file"); }

 

转载请注明原文地址: https://www.6miu.com/read-4150120.html

最新回复(0)