下载比较简单,只要有个网页路径就行 网页路径示例:http://192.168.1.21:8013/Data/LocationSystem.exe
但是上传不行,客户端上传之后,服务端需要设置接收方法。把接收数据保存到服务端
在IIS上挂载一个网站,里面链接到我们上传下载的文件夹
URI:http://192.168.1.21:8013/Data 本地路径:C:\Users\Administrator\Desktop\网页所在文件夹\Data
1.客户端
项目内使用了BestHttpPro插件,所以默认用了这个插件,去实现上传和下载的功能
A.使用BestHttp下载文件:
[ContextMenu("Download")]
public void StartDownload()
{
var request = new HTTPRequest(new System.Uri("http://192.168.1.21:8013/Data/LocationSystem.exe"), (req, resp) => {
//下载完成之后执行
List
// 把下载的文件保存到E盘根目录
using (FileStream fs = new FileStream(@"E:\LocationSystem1.exe", FileMode.Append))
foreach (byte[] data in fragments) fs.Write(data, 0, data.Length);
if (resp.IsStreamingFinished) Debug.Log("Download finished!");
});
request.UseStreaming = true;
request.StreamFragmentSize = 1 * 1024 * 1024;// 1 megabyte
request.DisableCache = true;// already saving to a file, so turn off caching
request.OnProgress = OnLoadProgress;
request.Send();
}
//下载进度
void OnLoadProgress(HTTPRequest request, int download, int length)
{
float progressPercent = (download / (float)length) * 100.0f;
Debug.Log("Download: " + progressPercent.ToString("F2") + "%");
}
B:使用BestHttp上传文件:
[ContextMenu("UploadRawData")]
public void UploadSecond()
{
StartCoroutine(UploadFiles());
}
public IEnumerator UploadFiles()
{
string serverUrl = "http://localhost:8733/api/fileTransfer/uploadFiles";
var request = new HTTPRequest(new System.Uri(serverUrl), HTTPMethods.Post, OnFinished);
string fileName = @"E:\xxx.txt";
byte[] data = FileContent(fileName);
string fileName2 = @"E:\LocationSystem1.exe";
byte[] data2 = FileContent(fileName2);
request.AddBinaryData("BigFile", data, "xxxttttt1.txt");
request.AddBinaryData("BigFile", data2, "xxxeeeeee2.exe");
request.SetHeader("Content-Type", "application/octet-stream");
request.OnUploadProgress = OnUploadProgress;
request.DisableCache = true;
request.Send();
yield return null;
}
void OnFinished(HTTPRequest originalRequest, HTTPResponse response)
{
Debug.Log("finished...");
Debug.Log("Response:"+response.DataAsText);
}
void OnUploadProgress(HTTPRequest request, long uploaded, long length)
{
float progressPercent = (uploaded / (float)length) * 100.0f;
Debug.Log("Uploaded: " + progressPercent.ToString("F2") + "%");
}
C:使用UnityWebRequest上传文件(对应的,也可以使用这个下载文件)
[ContextMenu("PostWebapi")]
public void StartPost()
{
StartCoroutine(PostObject("http://localhost:8733/api/fileTransfer/uploadFiles", null, null));
}
public IEnumerator PostObject(string url, Action callback, Action
{
string[] path = new string[2];
path[0] = @"E:\ZTest\xxx.txt";
path[1] = @"E:\ZTest\xxxeee.txt";
WWWForm form = new WWWForm();
for (int i = 0; i < path.Length; i++)
{
byte[] uploadData = FileContent(path[i]);
form.AddBinaryData("files[]", uploadData, Path.GetFileName(path[i]));
}
using (UnityWebRequest www = UnityWebRequest.Post(url, form))
{
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log("错误:www.error =>" + www.error);
if (errorCallback != null)
{
errorCallback(www.error);
}
}
else
{
// Show results as text
string results = www.downloadHandler.text;
Debug.Log("Result:" + results);
if (callback != null) callback();
}
}
}
上面两种上传的方式,都用下面的方法,把文件读取成byte[]
private byte[] FileContent(string fileName)
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
try
{
byte[] buffur = new byte[fs.Length];
fs.Read(buffur, 0, (int)fs.Length);
return buffur;
}
catch (Exception ex)
{
throw ex;
}
}
}
2.服务端
服务端接收客户端上传的文件,需要设置一下最大接收Size。否则在传输大文件时,WeApi接收方法不会触发
设置如下:
找到启动WebApi的代码,设置MaxBufferSize和MaxRecievedMessageSize(这两个默认只有几十兆)
如果是.net 做的网页,去web.Config里设置,这一类能搜到很多资料。想反,我们在wpf中使用webapi传输数据的,资料还少点。
上面的设置完成后,新建一个FileTransferController用于接收客户端传输的文件
[RoutePrefix("api/fileTransfer")]
public class FileTransferController : ApiController
{
private string saveDirectoryPath = "";
[Route("uploadFiles")]
[HttpPost]
public IHttpActionResult GetUploadFile()
{
//把文件保存路径放在了App.config文件中了。打包后也可以动态修改。
//如果只是测试,给个默认路径saveDirectoryPath =@"E:\yourSaveDirectory"
if(string.IsNullOrEmpty(saveDirectoryPath))
{
//去除路径前后空格
saveDirectoryPath = AppSetting.FileTransferSaveDirctory.Trim();
//去除文件夹最后的\ 例如:E:\SaveTest\==》 E:\SaveTest
if (!string.IsNullOrEmpty(saveDirectoryPath) && saveDirectoryPath.EndsWith(@"\"))
{
saveDirectoryPath = saveDirectoryPath.Remove(saveDirectoryPath.Length - 1);
}
}
//判断文件夹是否存在
if (Directory.Exists(saveDirectoryPath) == false)
{
//创建用于存图片的文件夹
Directory.CreateDirectory(saveDirectoryPath);
}
//准备接收文件
var provider = new MultipartMemoryStreamProvider();
IEnumerable
//异步
Task.Factory.StartNew(() => parts = Request.Content.ReadAsMultipartAsync().Result.Contents, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Wait();
foreach (var item in parts)
{
//判断是否有文件
if (item.Headers.ContentDisposition.FileName == null)
continue;
var ms = item.ReadAsStreamAsync().Result;
using (var br = new BinaryReader(ms))
{
if (ms.Length <= 0)
break;
var data = br.ReadBytes((int)ms.Length);
//FileName对应客户端AddBinaryData中的FileName
string fileName = item.Headers.ContentDisposition.FileName.Replace("\"", "");
string newPath = saveDirectoryPath+@"\"+ fileName;
if (File.Exists(newPath)) newPath = GetFileSavePath(1,newPath);
File.WriteAllBytes(newPath, data);
}
}
return Json
}
///
/// 如有重复文件,则后缀+(1) locaiton.sql->location(1).sql
///
///
///
///
///
private static string GetFileSavePath(int currentIndex, string filePath)
{
try
{
string infoName = string.Format("{0}({1})",Path.GetFileNameWithoutExtension(filePath),currentIndex);
string fileName = string.Format(@"{0}\{1}{2}", Path.GetDirectoryName(filePath), infoName ,Path.GetExtension(filePath));
if (File.Exists(fileName))
{
currentIndex++;
return GetFileSavePath(currentIndex, filePath);
}
else
{
return fileName;
}
}catch(Exception e)
{
Log.Info("FileTransferController.Exception:"+e.ToString());
return filePath;
}
}
}
下载时碰到的问题:
像后缀名为 .unitypackage 这样的文件,下载时会报404 not found 错误。原因是这种类型的后缀,没在网页mimeType中添加。
解决方案:
1.在IIS中,找到对应网站,点击新增mimeType. 扩展名设置 *(*号代表支持任何文件) ,mimeType设置成 application/octet-stream;
2.如果不想让网页支持所有后缀,可以使用代码,去单独注册后缀
之前找资料,给的网站Index 都默认为1 .后面找到根据网站名称,获取对应index的方法。
下面代码,需要在nguget管理中,添加 System.DirectoryServices.dll
IISOle,需要右键引用-添加服务引用,找到Com类库,添加 ActiveDSIISNamespaceProvider
private void Button_Click(object sender, RoutedEventArgs e)
{
//zs是我网站的名称
string iisSite = string.Format("IIS://localhost/W3SVC/{0}/Root",GetWebIndex("zs"));
SetMimeTypeProperty(iisSite, ".json", "application/octet-stream");
}
///
/// 根据网站名,获取Index
///
///
///
private string GetWebIndex(string websiteName)
{
DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
foreach (DirectoryEntry dir in root.Children)
{
if (dir.SchemaClassName == "IIsWebServer")
{
string ww = dir.Properties["ServerComment"].Value.ToString();
if(ww==websiteName)
{
return dir.Name;
}
}
}
return "1";
}
///
/// 设置IIS的MIME类型,SetMimeTypeProperty("IIS://localhost/W3SVC/1/Root", ".hlp", "application/winhlp");
///
///
///
///
static void SetMimeTypeProperty(string metabasePath, string newExtension, string newMimeType)
{
try
{
DirectoryEntry path = new DirectoryEntry(metabasePath);
PropertyValueCollection propValues = path.Properties["MimeMap"];
Console.WriteLine(" Old value of MimeMap has {0} elements", propValues.Count);
object exists = null;
foreach (object value in propValues)
{
// IISOle requires a reference to the Active DS IIS Namespace Provider in Visual Studio .NET
IISOle.IISMimeType mimetypeObj = (IISOle.IISMimeType)value;
Console.WriteLine(" {0}->{1}", mimetypeObj.Extension, mimetypeObj.MimeType);
if (newExtension == mimetypeObj.Extension)
exists = value;
}
if (null != exists)
{
propValues.Remove(exists);
Console.WriteLine(" Found an entry for {0}; removing it before adding the new one.", newExtension);
}
IISOle.MimeMapClass newObj = new IISOle.MimeMapClass();
newObj.Extension = newExtension;
newObj.MimeType = newMimeType;
propValues.Add(newObj);
path.CommitChanges();
Console.WriteLine(" Done.");
}
catch (Exception ex)
{
if ("HRESULT 0x80005006" == ex.Message)
Console.WriteLine(" Property MimeMap does not exist at {0}", metabasePath);
else
Console.WriteLine("Failed in SetMimeTypeProperty with the following exception: \n{0}", ex.Message);
}
}