springboot集成Stream上传插件+图片缩略图+视频缩略图

最近项目需要做上传功能,网上搜索了一下各种的上传插件,最后选择了stream插件,stream支持暂停上传、进度展示、批量上传等核心功能,样式也可以自定义,可以集成bootstrap或layui等框架,比较符合预期。在demo中,我也集成了图片缩略图的生成,视频缩略图的截取等功能,有兴趣的可以看一下

Stream插件:http://twinkling.cn/

首先围观一下


是不是感觉不错,至少我认为是可以的,因为项目本身用的是layui,Stream官网的自定义样式例子用的是bootstrap,我也懒得改了,直接又把bootstrap加入到项目中,有兴趣有时间的同学可以用layui的样式改造一下。

首先说,该控件虽然可以选择多文件同时上传,但文件之间的上传还是串行的,即只允许同时上传一个文件,下面贴出核心的代码,完整的例子详情请在demo中查看

前端代码:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>上传插件集成</title>
	<meta name="renderer" content="webkit">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
	<meta name="apple-mobile-web-app-status-bar-style" content="black">
	<meta name="apple-mobile-web-app-capable" content="yes">
	<meta name="format-detection" content="telephone=no">
	<link rel="stylesheet" href="/layui-2.3.0/css/layui.css" media="all" />
	<link href="/streamUpload/css/stream-v1.css" rel="stylesheet" type="text/css">
	<link href="/bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="childrenBody" style="width: 95%">
	<div class="layui-upload" style="margin-left: 15px;margin-top: 15px;width: 100%">
	  <button type="button" class="layui-btn layui-btn-normal margin-left" id="uploadFileList">选择多文件</button>
	  <div class="layui-upload-list" style="width: 100%">
	    <div class="container" style="width: 100%;min-width: 550px;">
			<div class="row clearfix">
				<div class="col-md-7 column" style="width: 80%;overflow: auto;max-height: 400px;">
					<table id="data_table" class="layui-table" lay-skin="line" style="width: 100%;min-width: 500px;">
						<thead>
							<tr>
								<th>文件名</th>
								<th style="width: 40%">进度</th>
								<th style="min-width: 60px">大小</th>
								<th style="min-width: 70px">操作</th>
							</tr>
						</thead>
						<tbody id="bootstrap-stream-container">
						</tbody>
					</table>
				</div>
			</div>
		</div>
		<div class="container" style="width: 100%">
			<div class="row clearfix" style="width: 100%">
				<div class="col-md-7 column" style="width: 80%">
					<table style="margin-top: 10px;width: 100%" id="stream_total_progress_bar">
						<tr>
							<th style="min-width: 500px;">
								<div class="progress">
								  <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
								  </div>
								</div>
							</th>
						</tr>
						<tr>
							<th>
								<span class="stream_total_size"></span>
								<span class="stream_total_percent"></span>
							</th>
						</tr>
					</table>
				</div>
			</div>
		</div>
		<div class="margin-left">
			<button type="button" class="layui-btn start" id="startUploadFileButton">
				<i class="layui-icon"></i>开始上传
			</button>
			<button type="button" class="layui-btn" id="canleUploadFileButton">
				<i class="layui-icon"></i>取消上传
			</button>
		</div>
	  </div>
	</div>  
	
	<script type="text/javascript" src="/layui-2.3.0/layui.js"></script>
	<script type="text/javascript" src="/streamUpload/js/stream-v1.js"></script>
	<script src="/jquery/jquery-3.3.1.min.js"></script>
	<script type="text/javascript" src="/bootstrap-3.3.7/js/bootstrap.min.js"></script>
	
	<script type="text/javascript">
	var config = {
			enabled: true, /** 是否启用文件选择,默认是true */
			customered: true,
			multipleFiles: true, /** 是否允许同时选择多个文件,默认是false */	
			autoRemoveCompleted: false, /** 是否自动移除已经上传完毕的文件,非自定义UI有效(customered:false),默认是false */
			autoUploading: false, /** 当选择完文件是否自动上传,默认是true */
			fileFieldName: "FileData", /** 相当于指定<input type="file" name="FileData">,默认是FileData */
			maxSize: 2147483648, /** 当_t.bStreaming = false 时(也就是Flash上传时),2G就是最大的文件上传大小!所以一般需要 */
			simLimit: 200, /** 允许同时选择文件上传的个数(包含已经上传过的) */
			//extFilters: [".ppt",".pptx",".doc",".docx",".xls",".xlsx",".pdf"], /** 默认是全部允许,即 [] */
			browseFileId : "uploadFileList", /** 文件选择的Dom Id,如果不指定,默认是i_select_files */
			browseFileBtn : "", /** 选择文件的按钮内容,非自定义UI有效(customered:false) */
			filesQueueId : "i_stream_files_queue", /** 文件上传进度显示框ID,非自定义UI有效(customered:false) */
			filesQueueHeight : 450, /** 文件上传进度显示框的高,非自定义UI有效(customered:false),默认450px */
			messagerId : "i_stream_message_container", /** 消息框的Id,当没有自定义onXXX函数,系统会显示onXXX的部分提示信息,如果没有i_stream_message_container则不显示 */
			uploadURL : "/uploadFile",
			tokenURL : "/queryToken",
			postVarsPerFile:{
			},
			onSelect: function(files) {
			},
			onMaxSizeExceed: function(file) {
				$("#i_error_tips > span.text-message").append("文件[name="+file.name+", size="+file.formatSize+"]超过文件大小限制‵"+file.formatLimitSize+"‵,将不会被上传!<br>");
			},
			onFileCountExceed : function(selected, limit) {
				$("#i_error_tips > span.text-message").append("同时最多上传<strong>"+limit+"</strong>个文件,但是已选择<strong>"+selected+"</strong>个<br>");
			},
			onExtNameMismatch: function(info) {
				$("#i_error_tips > span.text-message").append("<strong>"+info.name+"</strong>文件类型不匹配[<strong>"+info.filters.toString() + "</strong>]<br>");
			},
			onAddTask: function(file) {
				 var file = '<tr id="' + file.id + '" class="template-upload fade in">' +
			     '<td><span class="preview">'+file.name+'</span></td>' +
			     '<td>' +
			     '    <div> <span class="message-text" style="font-size: 13px"></span></div>' +
			     '    <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">' +
				'			<div class="progress-bar progress-bar-success" title="" style="width: 0%;"></div>' +
				'		</div>' +
			     '</td>' +
			     '<td><p class="size">' + file.formatSize + '</p>' +
			     '</td>' +
			     '<td><span class="glyphicon glyphicon-remove" onClick="javascript:_t.cancelOne(\'' + file.id + '\')"></span>' +
			     '</td></tr>';
				$("#bootstrap-stream-container").append(file);
			},
			onUploadProgress: function(file) {
				var $bar = $("#"+file.id).find("div.progress-bar");
				$bar.css("width", file.percent + "%");
				var $message = $("#"+file.id).find("span.message-text");
				$message.text("已上传:" + file.formatLoaded + "/" + file.formatSize + "(" + file.percent + "%" + ") 速  度:" + file.formatSpeed);
				
				var $total = $("#stream_total_progress_bar");
				$total.find("div.progress-bar").css("width", file.totalPercent + "%");
				$total.find("span.stream_total_size").html(file.formatTotalLoaded + "/" + file.formatTotalSize);
				$total.find("span.stream_total_percent").html(file.totalPercent + "%");
			},
			onStop: function() {
			},
			onCancel: function(file) {
				$("#"+file.id).remove();
				var $total = $("#stream_total_progress_bar");
				$total.find("div.progress-bar").css("width", file.totalPercent + "%");
				$total.find("span.stream_total_size").text(file.formatTotalLoaded + "/" + file.formatTotalSize);
				$total.find("span.stream_total_percent").text(file.totalPercent + "%");
				//console && console.log("-------------onCancel-------------------End");
			},
			onCancelAll: function(numbers) {
				$("#i_error_tips > span.text-message").append(numbers + " 个文件已被取消上传!!!");
			},
			onComplete: function(file) {
				/** 100% percent */
				var $bar = $("#"+file.id).find("div.progress-bar");
				$bar.css("width", file.percent + "%");
				var $message = $("#"+file.id).find("span.message-text");
				$message.text("已上传:" + file.formatLoaded + "/" + file.formatSize + "(" + file.percent + "%" + ")");
				/** remove the `cancel` button */
				var $cancelBtn = $("#"+file.id).find("td:last > span");
				$cancelBtn.remove();
				
				/** modify the total progress bar */
				var $total = $("#stream_total_progress_bar");
				$total.find("div.progress-bar").css("width", file.totalPercent + "%");
				$total.find("span.stream_total_size").text(file.formatTotalLoaded + "/" + file.formatTotalSize);
				$total.find("span.stream_total_percent").text(file.totalPercent + "%");
				
				//console && console.log("-------------onComplete-------------------End");
			},
			onQueueComplete: function(msg) {
				$("#startUploadFileButton").html('<i class="layui-icon"></i>开始上传');
				$("#startUploadFileButton").removeClass("stop").addClass("start");
				$("#returnListPageButton").removeClass("layui-btn-disabled");
				$("#returnListPageButton").prop("disabled",false);
			},
			onUploadError: function(status, msg) {
				$("#i_error_tips > span.text-message").append(msg + ", 状态码:" + status);
			}
		};
		var _t = new Stream(config);

		function cancelOne(id){
			_t.cancelOne(id);
		}

		$("#startUploadFileButton").click(function(){
			if($(this).hasClass("start")){
				$(this).html('<i class="layui-icon"></i>暂停上传');
				$(this).removeClass("start").addClass("stop");
				$("#returnListPageButton").addClass("layui-btn-disabled");
				$("#returnListPageButton").prop("disabled",true);
				_t.upload();
			}else{
				$(this).html('<i class="layui-icon"></i>开始上传');
				$(this).removeClass("stop").addClass("start");
				$("#returnListPageButton").removeClass("layui-btn-disabled");
				$("#returnListPageButton").prop("disabled",false);
				_t.stop();
			}
		});

		$("#canleUploadFileButton").click(function(){
			_t.cancel();
		});
	</script>
</body>
</html>


java代码:

TokenController

@Controller
public class TokenController {

	public static final String FILE_NAME_FIELD = "name";
	public static final String FILE_SIZE_FIELD = "size";
	public static final String FILE_TYPE = "fileType";
	public static final String TOKEN_FIELD = "token";
	public static final String SERVER_FIELD = "server";
	public static final String SUCCESS = "success";
	public static final String MESSAGE = "message";

	@RequestMapping(value = "/queryToken")
	public void firstdoget(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		doOptions(req, resp);
		String name = req.getParameter(FILE_NAME_FIELD); // 文件名
		String size = req.getParameter(FILE_SIZE_FIELD); // 文件大小
		String token = TokenUtil.generateToken(name, size); // 利用文件名和文件大小重新生成编码作为临时文件的名字

		PrintWriter writer = resp.getWriter();
		JSONObject json = new JSONObject();
		try {
			json.put(TOKEN_FIELD, token);
			json.put(SUCCESS, true);
			json.put(MESSAGE, "");
		} catch (JSONException e) {
		}
		writer.write(json.toString());
	}

	protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException {
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("application/json;charset=utf-8");
		resp.setHeader("Access-Control-Allow-Origin", "*");
		resp.setHeader("Access-Control-Allow-Headers", "Content-Range,Content-Type");
		resp.setHeader("Access-Control-Allow-Origin", "*");
		resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
	}
}

UploadController

@Controller
public class UploadController {

	static final int BUFFER_LENGTH = 10240;
	static final String START_FIELD = "start";
	public static final String CONTENT_RANGE_HEADER = "content-range";

	@Autowired
	private ImageAsync imageAsync;

	@Autowired
	private VideoAsync videoAsync;

	@RequestMapping(value = "/uploadFile", method = RequestMethod.GET)
	public void uploadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
		long start = 0;
		boolean success = true;
		String message = "";
		JSONObject json = new JSONObject();
		final String token = request.getParameter(TokenController.TOKEN_FIELD); // 文件名和大小的hashcode编码
		final String size = request.getParameter(TokenController.FILE_SIZE_FIELD); // 文件大小
		final String fileName = request.getParameter(TokenController.FILE_NAME_FIELD); // 文件名
		final PrintWriter writer = response.getWriter();
		try {
			doOptions(request, response);
			// 创建空文件,以及上级文件夹名
			File file = IoUtil.getTokenedFile(token);
			start = file.length();
			if (token.endsWith("_0") && "0".equals(size) && 0 == start)
				file.renameTo(IoUtil.getFile(fileName));
		} catch (FileNotFoundException e) {
			message = "Error: " + e.getMessage();
			success = false;
		} finally {
			try {
				if (success)
					json.put(START_FIELD, start);
				json.put(TokenController.SUCCESS, success);
				json.put(TokenController.MESSAGE, message);
			} catch (JSONException e) {

			}
			writer.write(json.toString());
			IoUtil.close(writer);
		}
	}

	@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
	public void uploadFileListPost(HttpServletRequest request, HttpServletResponse response)
			throws IOException, Exception {
		doOptions(request, response);
		// 文件名和大小的hashcode编码
		final String token = request.getParameter(TokenController.TOKEN_FIELD);
		// 文件名
		final String fileName = request.getParameter(TokenController.FILE_NAME_FIELD);
		Range range = IoUtil.parseRange(request);
		OutputStream out = null;
		InputStream content = null;
		final PrintWriter writer = response.getWriter();

		JSONObject json = new JSONObject();
		long start = 0;
		boolean success = true;
		String message = "";
		File f = IoUtil.getTokenedFile(token);
		try {
			if (f.length() != range.getFrom()) {
				/** drop this uploaded data */
				throw new StreamException(StreamException.ERROR_FILE_RANGE_START);
			}

			out = new FileOutputStream(f, true);
			content = request.getInputStream();
			int read = 0;
			final byte[] bytes = new byte[BUFFER_LENGTH];
			while ((read = content.read(bytes)) != -1) {
				out.write(bytes, 0, read);
				try {
					// 这里主要是控制读写速度,呈现给前端的是上传速度
					Thread.sleep(ConstantByProperties.uploadSpeed);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			start = f.length();
		} catch (StreamException se) {
			success = StreamException.ERROR_FILE_RANGE_START == se.getCode();
			message = "Code: " + se.getCode();
			throw new StreamException(se.getCode());
		} catch (FileNotFoundException fne) {
			message = "Code: " + StreamException.ERROR_FILE_NOT_EXIST;
			success = false;
			throw new FileNotFoundException();
		} catch (IOException io) {
			message = "IO Error: " + io.getMessage();
			success = false;
			throw new IOException(io);
		} finally {
			IoUtil.close(out);
			IoUtil.close(content);

			/** rename the file */
			Map<String, String> map = new HashMap<String, String>();

			if (range.getSize() == start) {
				/** fix the `renameTo` bug */
				try {
					String cgSubDir = ConstantByProperties.basePath;
					String uuid = UUID.randomUUID().toString();

					String fileSaveName = uuid + "." + fileName.split("\\.")[fileName.split("\\.").length - 1];

					String url = cgSubDir + fileSaveName;

					Path pathtrue = f.toPath().resolveSibling(url);
					File parentFile = pathtrue.toFile().getParentFile();
					if (!parentFile.exists()) {
						parentFile.mkdirs();
					}
					Files.move(f.toPath(), pathtrue);

					map.put("name", fileName);
					map.put("uuid", uuid);
					map.put("url", url);
					// 获得上传后的文件对象,可以做一些后期的处理,比如生成图片缩略图,视频缩略图等等,最好用异步的方式去执行这些操作,开启异步配置自行百度
					File newFile = pathtrue.toFile();

					// 生成图片缩略图,生成缩略图存放的路径跟原图路径是相同的
					imageAsync.createThumbnail(newFile);
					// 异步生成视频缩略图,第二个参数表示取(视频长度/xx)的那一帧作为缩略图
					videoAsync.randomGrabberFFmpegImage(pathtrue.toString(), 2);
				} catch (IOException e) {
					e.printStackTrace();
					success = false;
					message = "Rename file error: " + e.getMessage();
				}
			}
			try {
				if (success) {
					json.put(START_FIELD, start);
					json.put("map", map);
				}
				json.put(TokenController.SUCCESS, success);
				json.put(TokenController.MESSAGE, message);
			} catch (JSONException e) {
				System.out.println(e.toString());
			}
			writer.write(json.toString());
			IoUtil.close(writer);
		}
	}

	private void doOptions(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException {
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("application/json;charset=utf-8");
		resp.setHeader("Access-Control-Allow-Origin", "*");
		resp.setHeader("Access-Control-Allow-Headers", "Content-Range,Content-Type");
		resp.setHeader("Access-Control-Allow-Origin", "*");
		resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
	}
}

demo地址:https://github.com/iceSnowChen/upload-demo

ps:由于公司有加密机制,demo中的java文件会被加密,我做了一下备份,自己改一下就行了

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; namespace rkk0108.Controllers { /// <summary> /// 图片处理 /// http://www.cnblogs.com/wu-jian/ /// /// 吴剑 2011-02-20 创建 /// 吴剑 2012-08-08 修改 /// </summary> public class MyImageHelper { #region 正方型裁剪并放 /// <summary> /// 正方型裁剪 /// 以图片中心为轴心,截取正方型,然后等比放 /// 用于头像处理 /// </summary> /// <remarks>吴剑 2012-08-08</remarks> /// <param name="filePath">图片绝对地址</param> /// <param name="fileSaveUrl">略图存放地址</param> /// <param name="side">指定的边长(正方型)</param> /// <param name="quality">质量(范围0-100)</param> public static void CutForSquare(string filePath, string fileSaveUrl, int side, int quality) { FileStream fileStream = new FileStream(filePath, FileMode.Open); Stream fromFile = fileStream as Stream; //创建目录 string dir = Path.GetDirectoryName(fileSaveUrl); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); //原始图片(获取原始图片创建对象,并使用流中嵌入的颜色管理信息) System.Drawing.Image initImage = System.Drawing.Image.FromStream(fromFile, true); //原图宽高均小于模版,不作处理,直接保存 if (initImage.Width <= side && initImage.Height <= side) { initImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg); } else { //原始图片的宽、高 int initWidth = initImage.Width; int initHeight = initImage.Height; //非正方型先裁剪为正方型 if (initWidth != initHeight) { //截图对象 System.Drawing.Image pickedImage = null; System.Drawing.Graphics pickedG = null; //宽大于高的横图 if (initWidth > initHeight) { //对象实例化 pickedImage = new System.Drawing.Bitmap(initHeight, initHeight); pickedG = System.Drawing.Graphics.FromImage(pickedImage); //设置质量 pickedG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; pickedG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //定位 Rectangle fromR = new Rectangle((initWidth - initHeight) / 2, 0, initHeight, initHeight); Rectangle toR = new Rectangle(0, 0, initHeight, initHeight); //画图 pickedG.DrawImage(initImage, toR, fromR, System.Drawing.GraphicsUnit.Pixel); //重置宽 initWidth = initHeight; } //高大于宽的竖图 else { //对象实例化 pickedImage = new System.Drawing.Bitmap(initWidth, initWidth); pickedG = System.Drawing.Graphics.FromImage(pickedImage); //设置质量 pickedG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; pickedG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //定位 Rectangle fromR = new Rectangle(0, (initHeight - initWidth) / 2, initWidth, initWidth); Rectangle toR = new Rectangle(0, 0, initWidth, initWidth); //画图 pickedG.DrawImage(initImage, toR, fromR, System.Drawing.GraphicsUnit.Pixel); //重置高 initHeight = initWidth; } //将截图对象赋给原图 initImage = (System.Drawing.Image)pickedImage.Clone(); //释放截图资源 pickedG.Dispose(); pickedImage.Dispose(); } //略图对象 System.Drawing.Image resultImage = new System.Drawing.Bitmap(side, side); System.Drawing.Graphics resultG = System.Drawing.Graphics.FromImage(resultImage); //设置质量 resultG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; resultG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //用指定背景色清空画布 resultG.Clear(Color.White); //绘制略图 resultG.DrawImage(initImage, new System.Drawing.Rectangle(0, 0, side, side), new System.Drawing.Rectangle(0, 0, initWidth, initHeight), System.Drawing.GraphicsUnit.Pixel); //关键质量控制 //获取系统编码类型数组,包含了jpeg,bmp,png,gif,tiff ImageCodecInfo[] icis = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo ici = null; foreach (ImageCodecInfo i in icis) { if (i.MimeType == "image/jpeg" || i.MimeType == "image/bmp" || i.MimeType == "image/png" || i.MimeType == "image/gif") { ici = i; } } EncoderParameters ep = new EncoderParameters(1); ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)quality); //保存略图 resultImage.Save(fileSaveUrl, ici, ep); //释放关键质量控制所用资源 ep.Dispose(); //释放略图资源 resultG.Dispose(); resultImage.Dispose(); //释放原始图片资源 initImage.Dispose(); } } #endregion #region 自定义裁剪并放 /// <summary> /// 指定长宽裁剪 /// 按模版比例最大范围的裁剪图片放至模版尺寸 /// </summary> /// <remarks>吴剑 2012-08-08</remarks> /// <param name="fromFile">原图Stream对象</param> /// <param name="fileSaveUrl">保存路径</param> /// <param name="maxWidth">最大宽(单位:px)</param> /// <param name="maxHeight">最大高(单位:px)</param> /// <param name="quality">质量(范围0-100)</param> public static void CutForCustom(System.IO.Stream fromFile, string fileSaveUrl, int maxWidth, int maxHeight, int quality) { //从文件获取原始图片,并使用流中嵌入的颜色管理信息 System.Drawing.Image initImage = System.Drawing.Image.FromStream(fromFile, true); //原图宽高均小于模版,不作处理,直接保存 if (initImage.Width <= maxWidth && initImage.Height <= maxHeight) { initImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg); } else { //模版的宽高比例 double templateRate = (double)maxWidth / maxHeight; //原图片的宽高比例 double initRate = (double)initImage.Width / initImage.Height; //原图与模版比例相等,直接放 if (templateRate == initRate) { //按模版大小生成最终图片 System.Drawing.Image templateImage = new System.Drawing.Bitmap(maxWidth, maxHeight); System.Drawing.Graphics templateG = System.Drawing.Graphics.FromImage(templateImage); templateG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; templateG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; templateG.Clear(Color.White); templateG.DrawImage(initImage, new System.Drawing.Rectangle(0, 0, maxWidth, maxHeight), new System.Drawing.Rectangle(0, 0, initImage.Width, initImage.Height), System.Drawing.GraphicsUnit.Pixel); templateImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg); } //原图与模版比例不等,裁剪后放 else { //裁剪对象 System.Drawing.Image pickedImage = null; System.Drawing.Graphics pickedG = null; //定位 Rectangle fromR = new Rectangle(0, 0, 0, 0);//原图裁剪定位 Rectangle toR = new Rectangle(0, 0, 0, 0);//目标定位 //宽为标准进行裁剪 if (templateRate > initRate) { //裁剪对象实例化 pickedImage = new System.Drawing.Bitmap(initImage.Width, (int)System.Math.Floor(initImage.Width / templateRate)); pickedG = System.Drawing.Graphics.FromImage(pickedImage); //裁剪源定位 fromR.X = 0; fromR.Y = (int)System.Math.Floor((initImage.Height - initImage.Width / templateRate) / 2); fromR.Width = initImage.Width; fromR.Height = (int)System.Math.Floor(initImage.Width / templateRate); //裁剪目标定位 toR.X = 0; toR.Y = 0; toR.Width = initImage.Width; toR.Height = (int)System.Math.Floor(initImage.Width / templateRate); } //高为标准进行裁剪 else { pickedImage = new System.Drawing.Bitmap((int)System.Math.Floor(initImage.Height * templateRate), initImage.Height); pickedG = System.Drawing.Graphics.FromImage(pickedImage); fromR.X = (int)System.Math.Floor((initImage.Width - initImage.Height * templateRate) / 2); fromR.Y = 0; fromR.Width = (int)System.Math.Floor(initImage.Height * templateRate); fromR.Height = initImage.Height; toR.X = 0; toR.Y = 0; toR.Width = (int)System.Math.Floor(initImage.Height * templateRate); toR.Height = initImage.Height; } //设置质量 pickedG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; pickedG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //裁剪 pickedG.DrawImage(initImage, toR, fromR, System.Drawing.GraphicsUnit.Pixel); //按模版大小生成最终图片 System.Drawing.Image templateImage = new System.Drawing.Bitmap(maxWidth, maxHeight); System.Drawing.Graphics templateG = System.Drawing.Graphics.FromImage(templateImage); templateG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; templateG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; templateG.Clear(Color.White); templateG.DrawImage(pickedImage, new System.Drawing.Rectangle(0, 0, maxWidth, maxHeight), new System.Drawing.Rectangle(0, 0, pickedImage.Width, pickedImage.Height), System.Drawing.GraphicsUnit.Pixel); //关键质量控制 //获取系统编码类型数组,包含了jpeg,bmp,png,gif,tiff ImageCodecInfo[] icis = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo ici = null; foreach (ImageCodecInfo i in icis) { if (i.MimeType == "image/jpeg" || i.MimeType == "image/bmp" || i.MimeType == "image/png" || i.MimeType == "image/gif") { ici = i; } } EncoderParameters ep = new EncoderParameters(1); ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)quality); //保存略图 templateImage.Save(fileSaveUrl, ici, ep); //templateImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg); //释放资源 templateG.Dispose(); templateImage.Dispose(); pickedG.Dispose(); pickedImage.Dispose(); } } //释放资源 initImage.Dispose(); } #endregion #region 等比放 /// <summary> /// 图片等比放 /// </summary> /// <remarks>吴剑 2012-08-08</remarks> /// <param name="fromFile">原图Stream对象</param> /// <param name="savePath">略图存放地址</param> /// <param name="targetWidth">指定的最大宽度</param> /// <param name="targetHeight">指定的最大高度</param> /// <param name="watermarkText">水印文字(为""表示不使用水印)</param> /// <param name="watermarkImage">水印图片路径(为""表示不使用水印)</param> public static void ZoomAuto(System.IO.Stream fromFile, string savePath, System.Double targetWidth, System.Double targetHeight, string watermarkText, string watermarkImage) { //创建目录 string dir = Path.GetDirectoryName(savePath); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); //原始图片(获取原始图片创建对象,并使用流中嵌入的颜色管理信息) System.Drawing.Image initImage = System.Drawing.Image.FromStream(fromFile, true); //原图宽高均小于模版,不作处理,直接保存 if (initImage.Width <= targetWidth && initImage.Height <= targetHeight) { //文字水印 if (watermarkText != "") { using (System.Drawing.Graphics gWater = System.Drawing.Graphics.FromImage(initImage)) { System.Drawing.Font fontWater = new Font("黑体", 10); System.Drawing.Brush brushWater = new SolidBrush(Color.White); gWater.DrawString(watermarkText, fontWater, brushWater, 10, 10); gWater.Dispose(); } } //透明图片水印 if (watermarkImage != "") { if (File.Exists(watermarkImage)) { //获取水印图片 using (System.Drawing.Image wrImage = System.Drawing.Image.FromFile(watermarkImage)) { //水印绘制条件:原始图片宽高均大于或等于水印图片 if (initImage.Width >= wrImage.Width && initImage.Height >= wrImage.Height) { Graphics gWater = Graphics.FromImage(initImage); //透明属性 ImageAttributes imgAttributes = new ImageAttributes(); ColorMap colorMap = new ColorMap(); colorMap.OldColor = Color.FromArgb(255, 0, 255, 0); colorMap.NewColor = Color.FromArgb(0, 0, 0, 0); ColorMap[] remapTable = { colorMap }; imgAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap); float[][] colorMatrixElements = { new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, new float[] {0.0f, 0.0f, 0.0f, 0.5f, 0.0f},//透明度:0.5 new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f} }; ColorMatrix wmColorMatrix = new ColorMatrix(colorMatrixElements); imgAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); gWater.DrawImage(wrImage, new Rectangle(initImage.Width - wrImage.Width, initImage.Height - wrImage.Height, wrImage.Width, wrImage.Height), 0, 0, wrImage.Width, wrImage.Height, GraphicsUnit.Pixel, imgAttributes); gWater.Dispose(); } wrImage.Dispose(); } } } //保存 initImage.Save(savePath, System.Drawing.Imaging.ImageFormat.Jpeg); } else { //略图宽、高计算 double newWidth = initImage.Width; double newHeight = initImage.Height; //宽大于高或宽等于高(横图或正方) if (initImage.Width > initImage.Height || initImage.Width == initImage.Height) { //如果宽大于模版 if (initImage.Width > targetWidth) { //宽按模版,高按比例放 newWidth = targetWidth; newHeight = initImage.Height * (targetWidth / initImage.Width); } } //高大于宽(竖图) else { //如果高大于模版 if (initImage.Height > targetHeight) { //高按模版,宽按比例放 newHeight = targetHeight; newWidth = initImage.Width * (targetHeight / initImage.Height); } } //生成新图 //新建一个bmp图片 System.Drawing.Image newImage = new System.Drawing.Bitmap((int)newWidth, (int)newHeight); //新建一个画板 System.Drawing.Graphics newG = System.Drawing.Graphics.FromImage(newImage); //设置质量 newG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; newG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //置背景色 newG.Clear(Color.White); //画图 newG.DrawImage(initImage, new System.Drawing.Rectangle(0, 0, newImage.Width, newImage.Height), new System.Drawing.Rectangle(0, 0, initImage.Width, initImage.Height), System.Drawing.GraphicsUnit.Pixel); //文字水印 if (watermarkText != "") { using (System.Drawing.Graphics gWater = System.Drawing.Graphics.FromImage(newImage)) { System.Drawing.Font fontWater = new Font("宋体", 10); System.Drawing.Brush brushWater = new SolidBrush(Color.White); gWater.DrawString(watermarkText, fontWater, brushWater, 10, 10); gWater.Dispose(); } } //透明图片水印 if (watermarkImage != "") { if (File.Exists(watermarkImage)) { //获取水印图片 using (System.Drawing.Image wrImage = System.Drawing.Image.FromFile(watermarkImage)) { //水印绘制条件:原始图片宽高均大于或等于水印图片 if (newImage.Width >= wrImage.Width && newImage.Height >= wrImage.Height) { Graphics gWater = Graphics.FromImage(newImage); //透明属性 ImageAttributes imgAttributes = new ImageAttributes(); ColorMap colorMap = new ColorMap(); colorMap.OldColor = Color.FromArgb(255, 0, 255, 0); colorMap.NewColor = Color.FromArgb(0, 0, 0, 0); ColorMap[] remapTable = { colorMap }; imgAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap); float[][] colorMatrixElements = { new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, new float[] {0.0f, 0.0f, 0.0f, 0.5f, 0.0f},//透明度:0.5 new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f} }; ColorMatrix wmColorMatrix = new ColorMatrix(colorMatrixElements); imgAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); gWater.DrawImage(wrImage, new Rectangle(newImage.Width - wrImage.Width, newImage.Height - wrImage.Height, wrImage.Width, wrImage.Height), 0, 0, wrImage.Width, wrImage.Height, GraphicsUnit.Pixel, imgAttributes); gWater.Dispose(); } wrImage.Dispose(); } } } //保存略图 newImage.Save(savePath, System.Drawing.Imaging.ImageFormat.Jpeg); //释放资源 newG.Dispose(); newImage.Dispose(); initImage.Dispose(); } } #endregion #region 其它 /// <summary> /// 判断文件类型是否为WEB格式图片 /// (注:JPG,GIF,BMP,PNG) /// </summary> /// <param name="contentType">HttpPostedFile.ContentType</param> /// <returns></returns> public static bool IsWebImage(string contentType) { if (contentType == "image/pjpeg" || contentType == "image/jpeg" || contentType == "image/gif" || contentType == "image/bmp" || contentType == "image/png") { return true; } else { return false; } } #endregion }//end class }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值