现在微信小程序拍照上传的需求越来越多了,绝大部分小程序项目都会用到,虽然技术上没什么难度,但对于初学者来说,也是件费时费力的事情,三年前我在写这些代码的时候也是花费好几天的时间,最近有点空闲时间,于是就决定整理一下发布出来,有不足之处请多批评指正,废话不多说,先上效果图。
一、小程序端代码
1、wxml页面
<view class="searchTitle">
开始服务<text>请在服务开始前至少上传三张现场照片</text>
</view>
<view class="serviceContent">
<view class="picList">
<view wx:for="{{picList}}" wx:key='index' bindtap="handleImagePreview" wx:for-index="idx" data-idx="{{idx}}" class="picView">
<image class="pic" mode="aspectFill" src="{{item.filePath}}"></image>
<view class="delView" data-idx="{{idx}}" catchtap="delPic">
<i class="fa fa-trash-o fa-lg"></i>
</view>
</view>
<view class="picAdd" wx:if="{{picList.length<9}}" bindtap="chooseimage">
<image src="/img/addPic.png"></image>
</view>
</view>
<view class="inputItem">
<textarea bindinput="fwbzInput" value="{{fwbz}}" placeholder="服务备注"></textarea>
</view>
<view class="smallItem location">
<image class="smallImg" mode="widthFix" src="/img/address.png"></image>
<text wx:if="{{address!=''}}" class="smallText">{{tag}}位置:{{address}}</text>
<text wx:else class="smallText">{{tag}}位置:位置获取中...</text>
</view>
</view>
<view class="btnView">
<button id="saveBtn" bindtap="save" class="btnStyle" type="warn">提 交</button>
<button id="submitBtn" bindtap="back" style="margin-left:30rpx;" class="btnStyle" type="warn">返 回</button>
</view>
2、wxss页面
.searchTitle
{
height: 35px;
background-color: #f7fcff;
margin-top: 10rpx;
border-top: solid 1px #e6e6e6;
border-left: solid 1px #e6e6e6;
border-right: solid 1px #e6e6e6;
font-size: 14px;
line-height: 40px;
padding-left: 15px;
color: #000;
display: flex;
flex-direction: row;
align-items: center;
}
.btnStyle
{
letter-spacing: 3px;
flex-grow: 1;
color: #fff;
}
.btnView
{
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 20rpx;
flex-grow: 1;
}
.searchTitle text
{
font-size: 12px;
margin-left: 10rpx;
color: #999;
}
.serviceContent
{
border: solid 1px #e6e6e6;
}
.picList {
display: flex;
flex-direction: row;
align-items: center;
border-bottom: solid 1px #f3f3f3;
padding: 20rpx;
padding-top: 0rpx;
padding-right: 0rpx;
flex-wrap: wrap;
justify-content: flex-start;
}
.picView
{
width: 210rpx;
height: 210rpx;
background-color: #f3f3f3;
margin-top: 20rpx;
margin-right: 20rpx;
position: relative;
}
.pic
{
width: 210rpx;
height: 210rpx;
background-color: #f3f3f3;
}
.delView
{
background-color: #ff0000;
height: 56rpx;
width: 56rpx;
position:absolute;
right: 0px;
left: auto;
top: 0px;
color: #fff;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 28rpx;
}
.picAdd
{
width: 210rpx;
height: 210rpx;
background-color: #f3f3f3;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-top: 20rpx;
}
.picAdd:hover
{
background-color: #e3e3e3;
}
.picAdd image
{
width: 100rpx;
height: 80rpx;
}
.location:hover
{
color: #2ab6ff;
}
.smallImg
{
height: 20px;
width: 20px;
}
.smallText
{
flex-grow: 1;
font-size: 14px;
margin-left: 10px;
}
.smallItem {
display: flex;
flex-direction: row;
align-items: center;
margin-left: 20rpx;
margin-right: 20rpx;
justify-content: center;
min-height: 40px;
}
.inputItem
{
display: flex;
flex-direction: row;
justify-items: center;
align-items: center;
border-bottom: solid 1px #f3f3f3;
margin-left: 20rpx;
margin-right: 20rpx;
justify-content: space-between;
}
.inputItem text
{
width: 80px;
padding-top: 12px;
padding-bottom: 12px;
flex-grow: 0;
flex-shrink: 0;
}
.inputItem input
{
flex-grow: 1;
}
.inputItem textarea
{
flex-grow: 1;
margin-top: 10rpx;
height: 100rpx;
}
.location_hover
{
color: #ff4c0d;
}
3、js页面
var app=getApp();
Page({
/**
* 页面的初始数据
*/
data: {
address:"",
picList:[],
latitude:0,
longitude:0
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getPosition();//获取位置信息
},
chooseimage: function () {//选择图片
var that = this;
wx.chooseImage({
count: 9 - this.data.picList.length, // 默认9
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有//'original', 'compressed'
sourceType: ['camera'], // 可以指定来源是相册还是相机,默认二者都有'album', 'camera'
success: function (res) {
wx.showLoading({
title: '图片上传中...',
})
that.uploadImage(res.tempFilePaths, 0, that);
}
})
},
uploadImage: function (uploadingImages,i,that)//上传照片
{
var images = that.data.picList;
var uploadImgPath = uploadingImages[i];
var imgObj = new Object();
imgObj.filePath = "/img/upLoading.png";
images.push(imgObj);
that.setData({
picList: images
});
//上传照片
wx.uploadFile({
url: app.globalData.baseUrl + "upLoadImage.ashx",
filePath: uploadImgPath,
name: "file",
header: {
"Content-Type": "multipart/form-data"
},
success: function (res) {
var resImg = JSON.parse(res.data);
var imgObj = images[images.length-1];
imgObj.filePath = uploadImgPath;
imgObj.imgUrl = resImg.imgUrl;
imgObj.smallImgUrl = resImg.smallImgUrl;
imgObj.size = resImg.size;
that.setData({
picList: images
});
//上传下一张照片
i++
if (i < uploadingImages.length)
{
that.uploadImage(uploadingImages, i, that);
}
else
{
wx.hideLoading();
}
}
})
},
handleImagePreview(e) {//预览图片
const idx = e.currentTarget.dataset.idx;
const images = [];
for (var i = 0; i < this.data.picList.length;i++)
{
images.push(this.data.picList[i].filePath);
}
wx.previewImage({
current: images[idx], //当前预览的图片
urls: images, //所有要预览的图片
})
},
delPic:function(e){//删除图片
var idx = e.currentTarget.dataset.idx
var tempList = this.data.picList;
tempList.splice(idx, 1);
this.setData({
picList:tempList
});
},
getPosition() {//获取地理位置信息
let that = this;
wx.getLocation({
type: 'wgs84',
success: function (res) {
var latitude = res.latitude;
var longitude = res.longitude;
that.setData({
latitude: latitude,
longitude: longitude
});
var location = latitude + "," + longitude;
wx.request({
url: app.globalData.url,
data: {
appid: app.globalData.appid,
action: "getAddress",
location: location
},
method: 'GET',
success: (res) => {
if (res.statusCode == 200 && res.data.status == 0) {
var country = res.data.result.address_component.nation;//国家
var province = res.data.result.address_component.province;//省
var city = res.data.result.address_component.city;//市
var county = res.data.result.address_component.district;//区
var street = res.data.result.address_component.street;//街道
var address = country + province + city + county + street;
that.setData({
address: address
});
}
}
})
},
fail() {
that.setData({
address: "位置获取失败"
});
}
})
},
back:function(e){
wx.navigateBack({});
},
save:function(e){
var that=this;
if (this.data.picList.length<3) {
app.showMsg("请至少拍摄三张照片。");
return;
}
wx.showLoading({
title: '数据保存中...',
mask: true
});
var picTempList=[];
for(var i=0;i<that.data.picList.length;i++)
{
var pic=that.data.picList[i];
var picTemp=new Object();
picTemp.name = pic.imgUrl;
picTemp.path = "UploadFile/"+pic.imgUrl;
picTemp.smallImgUrl = "UploadFile/"+pic.smallImgUrl;
picTemp.size = pic.size;
picTempList.push(picTemp);
}
var picJson=JSON.stringify(picTempList);
console.log(picJson);
//将picJson做为参数传到服务器,由服务器写入数据库,后面的代码就省略了...
},
})
二、后端代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
namespace PicUpload
{
/// <summary>
/// upLoadImage 的摘要说明
/// </summary>
public class upLoadImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
HttpFileCollection files = context.Request.Files;
if (files.Count > 0)
{
string imgName = DateTime.Now.ToString("yyyyMMddhhmmssfff");
string oldFileName = System.IO.Path.GetFileName(files[0].FileName);
string hz = "";
if (oldFileName.IndexOf(".") >= 0)
{
hz = oldFileName.Substring(oldFileName.LastIndexOf(".")).Trim();
}
string path = context.Server.MapPath("/UploadFile/");
files[0].SaveAs(path + imgName + hz);
//生成缩略图
MakeThumbnail(path + imgName + hz, path + imgName + "slt" + hz, 300, 300, "DB", hz);
Image img = new Image();
img.size = files[0].ContentLength;
img.imgUrl = imgName + hz;
img.smallImgUrl = imgName + "slt" + hz;
img.tag = "1";
img.msg = "上传成功!";
img.fileName = img.imgUrl;
string res = getJsonStr(img).ToString();
context.Response.Write(res);
}
}
catch (Exception ex)
{
context.Response.Write(ex.ToString());
}
}
#region 将对象转换为Json数据
public static System.Text.StringBuilder getJsonStr(object o)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
StringBuilder sb = new StringBuilder();
jss.Serialize(o, sb);
return sb;
}
#endregion
#region 生成缩略图
/// <summary>
/// 生成缩略图
/// </summary>
/// <param name="originalImagePath">源图路径(物理路径)</param>
/// <param name="thumbnailPath">缩略图路径(物理路径)</param>
/// <param name="width">缩略图宽度</param>
/// <param name="height">缩略图高度</param>
/// <param name="mode">生成缩略图的方式。"HW":指定高宽缩放(可能变形),"W":指定宽,高按比例,"H":指定高,宽按比例,"Cut":指定高宽裁减(不变形),"DB":等比缩放(不变形,如果高大按高,宽大按宽缩放)</param>
public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, string mode, string type)
{
System.Drawing.Image originalImage = System.Drawing.Image.FromFile(originalImagePath);
int towidth = width;
int toheight = height;
int x = 0;
int y = 0;
int ow = originalImage.Width;
int oh = originalImage.Height;
switch (mode)
{
case "HW"://指定高宽缩放(可能变形)
break;
case "W"://指定宽,高按比例
toheight = originalImage.Height * width / originalImage.Width;
break;
case "H"://指定高,宽按比例
towidth = originalImage.Width * height / originalImage.Height;
break;
case "Cut"://指定高宽裁减(不变形)
if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
{
oh = originalImage.Height;
ow = originalImage.Height * towidth / toheight;
y = 0;
x = (originalImage.Width - ow) / 2;
}
else
{
ow = originalImage.Width;
oh = originalImage.Width * height / towidth;
x = 0;
y = (originalImage.Height - oh) / 2;
}
break;
case "DB"://等比缩放(不变形,如果高大按高,宽大按宽缩放)
if ((double)originalImage.Width / (double)towidth < (double)originalImage.Height / (double)toheight)
{
toheight = height;
towidth = originalImage.Width * height / originalImage.Height;
}
else
{
towidth = width;
toheight = originalImage.Height * width / originalImage.Width;
}
break;
default:
break;
}
//新建一个bmp图片
System.Drawing.Image bitmap = new System.Drawing.Bitmap(towidth, toheight);
//新建一个画板
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);
//设置高质量插值法
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
//设置高质量,低速度呈现平滑程度
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//清空画布并以透明背景色填充
g.Clear(System.Drawing.Color.Transparent);
//在指定位置并且按指定大小绘制原图片的指定部分
g.DrawImage(originalImage, new System.Drawing.Rectangle(0, 0, towidth, toheight),
new System.Drawing.Rectangle(x, y, ow, oh),
System.Drawing.GraphicsUnit.Pixel);
try
{
//保存缩略图
switch (type.ToLower())
{
case ".jpg":
bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case ".bmp":
bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Bmp);
break;
case ".gif":
bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Gif);
break;
case ".png":
bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Png);
break;
}
}
catch (System.Exception e)
{
throw e;
}
finally
{
originalImage.Dispose();
bitmap.Dispose();
g.Dispose();
}
}
#endregion
public bool IsReusable
{
get
{
return false;
}
}
}
public class Image
{
public string imgUrl;
public string smallImgUrl;
public int size;
public string tag;
public string msg;
public string fileName;
}
}