0、背景 老项目使用WCF 提供web服务,现在开发安卓原生应用需要上传图片,网上找了些资料和代码发现文件中文名称处理有点异常,修改后贴出来。 1、代码 1.1 C#后端代码 服务接口[O
0、背景
老项目使用WCF 提供web服务,现在开发安卓原生应用需要上传图片,网上找了些资料和代码发现文件中文名称处理有点异常,修改后贴出来。
1、代码
1.1 C#后端代码
服务接口
[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
Dictionary<string, string> ModifyImg(Stream image);
服务实现类
public Dictionary<string, string> ModifyImg(Stream image)
{
BOUploadImg bOUploadImg = new BOUploadImg();
var dic = bOUploadImg.UploadWithFormData(image);
BOFactory.boQmsBarcodeImage.Save(dic);
return dic;
}
public class BOUploadImg
{
public Dictionary<string, string> Upload(Stream file)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
try
{
string rootPath = "~/upload/";
string realRoot = System.Configuration.ConfigurationManager.AppSettings["RemoteUploadFileDir"];
using (MemoryStream ms = new MemoryStream())
{
file.CopyTo(ms);
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
int firstLineLen = Encoding.UTF8.GetBytes(sr.ReadLine() ?? "").Length;
var position = firstLineLen + 2;
var line = sr.ReadLine();
var filename = "";
var ID = DateTime.Now.ToString("yyyyMMddHHmmssffff", DateTimeFormatInfo.InvariantInfo);
if (!string.IsNullOrEmpty(line))
{
int idx = line.IndexOf("filename", StringComparison.CurrentCultureIgnoreCase);
filename += line.Substring(idx + 9).Replace("\"", "");
}
string Extension = "";
int index = filename.LastIndexOf('.');
if (index > 0)
{
Extension = filename.Substring(filename.LastIndexOf('.') + 1);
}
while (line != null)
{
// 特别是第二行含文件名称,可能含中文,所以不能直接用line.Length
// 因为line.Length是字符个数,不是字节个数
position += Encoding.UTF8.GetBytes(line).Length + 2;
if (line == "")
break;
line = sr.ReadLine();
}
ms.Position = position;
ms.SetLength(ms.Length - (firstLineLen + 6));
var uploadStream = new MemoryStream();
ms.CopyTo(uploadStream);
uploadStream.Position = 0;
try
{
//文件存储地址
string folder = "";
string dirPath = CheckTodayDir(realRoot, out folder);
string realPath = Path.Combine(dirPath, string.Format("{0}.{1}", ID, Extension));
string IMAGE_REAL_NAME = string.Format("{0}.{1}", ID, Extension);
string IMAGE_PATH = rootPath + folder + "/" + IMAGE_REAL_NAME;
dic.Add("FILE_REAL_NAME", IMAGE_REAL_NAME);
dic.Add("FILE_PATH", IMAGE_PATH);//URL PATH
dic.Add("FILE_OLD_NAME", filename);
dic.Add("FILE_EXTENSION", Extension);
File.WriteAllBytes(realPath, uploadStream.ToArray());
}
catch { }
}
}
return dic;
}
catch (Exception)
{
return dic;
}
}
public Dictionary<string, string> UploadWithFormData(Stream stream)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
try
{
string rootPath = "~/upload/";
string realRoot = System.Configuration.ConfigurationManager.AppSettings["RemoteUploadFileDir"];
FormdataCase formdataCase = new FormdataCase(stream);
var ID = DateTime.Now.ToString("yyyyMMddHHmmssffff", DateTimeFormatInfo.InvariantInfo);
string Extension = "";
int index = formdataCase.Filename.LastIndexOf('.');
if (index > 0)
{
Extension = formdataCase.Filename.Substring(formdataCase.Filename.LastIndexOf('.') + 1);
}
//文件存储地址
string folder = "";
string dirPath = CheckTodayDir(realRoot, out folder);
string realPath = Path.Combine(dirPath, string.Format("{0}.{1}", ID, Extension));
string IMAGE_REAL_NAME = string.Format("{0}.{1}", ID, Extension);
string IMAGE_PATH = rootPath + folder + "/" + IMAGE_REAL_NAME;
dic.Add("FILE_REAL_NAME", IMAGE_REAL_NAME);
dic.Add("FILE_PATH", IMAGE_PATH);//URL PATH
dic.Add("FILE_OLD_NAME", formdataCase.Filename);
dic.Add("FILE_EXTENSION", Extension);
if(formdataCase.Parameters != null && formdataCase.Parameters.Count > 0)
{
foreach(var keyValue in formdataCase.Parameters)
{
dic.Add(keyValue.Key, keyValue.Value);
}
}
File.WriteAllBytes(realPath, formdataCase.FileContents.ToArray());
return dic;
}
catch(Exception ex)
{
dic.Add("ERROR", ex.Message);
return dic;
}
}
private static string CheckTodayDir(string root, out string folder)
{
folder = DateTime.Now.ToString("yyyyMMdd");
string path = Path.Combine(root, folder);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
}
public class FormdataCase
{
/// <summary>
/// 参数集合
/// </summary>
public IDictionary<string, string> Parameters = new Dictionary<string, string>();
/// <summary>
/// 是否解析成功
/// </summary>
public bool Success { get; private set; }
/// <summary>
/// 请求类型
/// </summary>
public string ContentType { get; private set; }
/// <summary>
/// 上传的文件名
/// </summary>
public string Filename { get; private set; }
/// <summary>
/// 上传的文件内容
/// </summary>
public byte[] FileContents { get; private set; }
/// <summary>
/// 解析multipart/form-data格式的文件请求,默认编码为utf8
/// </summary>
/// <param name="stream"></param>
public FormdataCase(Stream stream)
{
Parse(stream, Encoding.UTF8);
}
/// <summary>
/// 解析form-data
/// </summary>
/// <param name="stream">可带参数,并不是只可以放一个文件</param>
/// <param name="encoding">utf8</param>
private void Parse(Stream stream, Encoding encoding)
{
Success = false;
var data = ToByteArray(stream);//将文件流转为byte[]
var content = encoding.GetString(data);//将byte[]转为string字符串
var delimiterEndIndex = content.IndexOf("\r\n", StringComparison.Ordinal);
if (delimiterEndIndex > -1)
{
var delimiter = content.Substring(0, content.IndexOf("\r\n", StringComparison.Ordinal)).Trim();
var sections = content.Split(new[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
foreach (var s in sections)
{
if (s.Contains("Content-Disposition"))
{
//获取form-data中的参数名称
var nameMatch = new Regex(@"(?<=name\=\"")(.*?)(?=\"")").Match(s);
var name = nameMatch.Value.Trim().ToLower();
//这里由于文件的参数名称为file,当获取到参数名称等于 file时,可以将文件内容截取出来,参数不是文件时将该参数存入泛型集合Parameters中。
if (name == "file")
{
var re = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");
var contentTypeMatch = re.Match(content);
//获取文件名
re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
var filenameMatch = re.Match(content);
//截取文件
if (contentTypeMatch.Success && filenameMatch.Success)
{
ContentType = contentTypeMatch.Value.Trim();
Filename = filenameMatch.Value.Trim();
var startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;
//这里取到的是字符数有中文需要取字节数
startIndex = Encoding.UTF8.GetBytes(content.Substring(0, startIndex)).Length;
var delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
var endIndex = IndexOf(data, delimiterBytes, startIndex);
var contentLength = endIndex - startIndex;//计算文件流长度
var fileData = new byte[contentLength];
Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
FileContents = fileData;
}
}
else if (!string.IsNullOrWhiteSpace(name))
{
//截取非文件参数,并将参数名称与参数值保存在泛型集合Parameters中。
var startIndex = nameMatch.Index + nameMatch.Length + "\r\n\r\n".Length;
Parameters.Add(name, s.Substring(startIndex).TrimEnd('\r', '\n').Trim());
}
}
}
if (FileContents != null || Parameters.Count != 0)
{
Success = true;
}
}
}
/// <summary>
/// 获取文件流末尾
/// </summary>
/// <param name="searchWithin"></param>
/// <param name="serachFor"></param>
/// <param name="startIndex"></param>
/// <returns></returns>
public static int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex)
{
var index = 0;
var startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
if (startPos != -1)
{
while (startPos + index < searchWithin.Length)
{
if (searchWithin[startPos + index] == serachFor[index])
{
index++;
if (index == serachFor.Length)
{
return startPos;
}
}
else
{
startPos = Array.IndexOf(searchWithin, serachFor[0], startPos + index);
if (startPos == -1)
{
return -1;
}
index = 0;
}
}
}
return -1;
}
/// <summary>
/// 将stream转为byte[]
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static byte[] ToByteArray(Stream stream)
{
var buffer = new byte[32768];
using (var ms = new MemoryStream())
{
while (true)
{
var read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
{
return ms.ToArray();
}
ms.Write(buffer, 0, read);
}
}
}
}
1.2 HTML 上传测试
<html>
<head>upload file to wcf iis</head>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.min.js"></script>
<body>
<input id="imgput" type="file" accept="image/*" onchange="selectimg(this);" />
<img id='imgtest' src="#" alt="Alternate Text" width="25px" />
<script type="text/javascript">
function selectimg(file) {
var url = null;
if (window.createobjectURL) {
url = window.createObjectURL(file.files[0]);//预览图片,浏览器支持不同
}
else if (window.URL) {
url = window.URL.createObjectURL(file.files[0]);
} else if (window.webkitURL) {
url = window.webkitURL.createObjectURL(file.files[0]);
}
var pimg = file.files[0];//获取图片文件
if (pimg.size > 1024 * 500) {
alert("文件不能超过500KB");
}
else {
var format = new FormData();//构建表单信息
var name = "file";
format.append(name, pimg);
format.append("age", 39);
format.append("address", "nanjing");
$("#imgtest").attr("src", url);
$.ajax({
url: "http://localhost:17880/MESOperationService.svc/ModifyImg",
type: "post",
data: format,
processData: false,//这里设置为false,回传流文件
dataType: 'json',
contentType: 'application/x-www-form-urlencoded',
async: false,
success: function (result) {
alert(JSON.stringify(result));
}
});
}
}
</script>
</body>
</html>
【感谢龙石为本站提供数据api平台http://www.longshidata.com/pages/exchange.html】