本地服务的文件上传与远程服务的文件上传(图片上传)

文件上传属于常见业务,很多地方都用的到(比如图片上传);

确切的说,这里的“本地”是指的项目所在的服务端,只是在项目服务端再次请求另外一个服务端进行文件二次上传。

比如:我们上传图片的时候,请求项目的服务器需要上传一份,同时还要上传一份到cdn服务器。

示例使用控件: el-upload 作为演示

 1 <style>
 2         .uploader {
 3             border: 1px dashed #d9d9d9;
 4             border-radius: 6px;
 5             cursor: pointer;
 6             position: relative;
 7             overflow: hidden;
 8         }
 9 
10             .uploader:hover {
11                 border-color: #409EFF;
12             }
13 
14         .avatar-uploader-icon {
15             font-size: 28px;
16             color: #8c939d;
17             text-align: center;
18         }
19 
20         .banners-size {
21             width: 280px;
22             height: 120px;
23             line-height: 120px;
24         }
25 
26         .avatar-banners {
27             width: 280px;
28             height: 120px;
29             background-size: cover;
30         }
31 
32         .el-upload__tip {
33             color: red;
34         }
35     </style>
View Code
 1 <el-upload class="upload-demo"
 2            ref="banners"
 3            :limit="1"
 4            action="https://jsonplaceholder.typicode.com/posts/"
 5            accept="image/jpeg,image/png"
 6            name="bannersImg"
 7            :http-request="uploadFile"
 8            :auto-upload="false">
 9     <el-button slot="trigger" size="small" type="primary" v-on:click="selectUpload('bannersImg')">选取文件</el-button>
10     <el-button style="margin-left: 10px;" size="small" type="success" v-on:click="submitUpload('bannersImg')">确定上传</el-button>
11     <div slot="tip" class="el-upload__tip">只能上传jpg文件,且不超过200kb,尺寸:440x240</div>
12 </el-upload>
13 <div class="uploader banners-size">
14     <img v-if="banners_imageUrl" :src="banners_imageUrl" class="avatar-banners">
15 </div>

前端核心代码:

 1                //选取文件
 2                 selectUpload: function (obj) {
 3                     this.clearFiles(obj);
 4                 },
 5                 //确定上传
 6                 submitUpload: function (obj) {
 7                      this.$refs.banners.submit();
 8                 },
 9                 //清除文件状态
10                 clearFiles: function (filename) {
11                       this.$refs.banners.clearFiles();
12                 },
13 
14                 //文件上传
15                 uploadFile: function (params) {
16                     //console.log(params);
17                     var _filename = params.filename;
18 
19                     //判断图片格式
20                     const isJPG = params.file.type === 'image/jpeg';
21                     if (!isJPG) {
22                         this.$message.error('上传图片只能是 JPG 格式!');
23                         this.clearFiles(_filename);
24                         return isJPG;
25                     }
26                      this.BannersUpload(params.file);
27                 },
28                 //图片上传
29                 BannersUpload: function (file) {
30                     const isLtSize = file.size / 1024 / 1024 / 1024 < 20;  //不能超过xx kb
31                     if (!isLtSize) {
32                         this.$message.error('上传图片大小不能超过 20kb!');
33                         this.clearFiles(file.filename);
34                         return isLtSize;
35                     }
36 
37                     //执行上传操作
38                     this.FileUpload(file)
39                         .then(res => {   //返回结果
40                             var getResult = JSON.parse(res.data);
41                             //成功
42                             if (getResult.Code == 0) {
43                                 this.$message.success('上传成功');
44                                 this.banners_imageUrl = getResult.Data;
45                                 this.addForm.BannersImg = getResult.Data;
46                             }
47                             //错误
48                             if (getResult.Code == 1) {
49                                 if (getResult.Message) {
50                                     this.$message.error(getResult.Message);
51                                 }
52                             }
53                         }).catch(function (res) {
54                             this.$message.success('请求异常');
55                         });
56                 },
57                 //文件上传
58                 FileUpload: function (file) {
59                     var fd = new FormData();
60                     fd.append("filedata", file);
61                     //异步获取
62                     return axios.request({
63                         method: 'post',
64                         baseURL: this.apiUrl,
65                         url: '/WxLive/UploadImg',
66                         params: { "filename": "filedata" },   //是即将与请求一起发送的 URL 参数
67                         data: fd,     //浏览器专属:FormData, File, Blob  必须是以下类型之一:string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
68                         headers: { "Content-Type": "multipart/form-data;charset=UTF-8" },
69                     });
70                 }
View Code

本地服务器上传接口:

 1         /// <summary>
 2         /// 本地上传图片
 3         /// </summary>
 4         /// <returns></returns>
 5         [HttpPost]
 6         public JsonResult UploadImg(string filename)
 7         {
 8             var result = new Common.CommonResult(1, "网络请求错误");
 9             try
10             {
11                 string basePath = ConfigurationManager.AppSettings["basePath"] ?? "\Images";    //服务器上传文件夹
12                 string imgpath = string.Empty;
13 
14                 HttpPostedFileBase file = Request.Files.Get(filename);  //从browser传过来的的文件
15                 //HttpPostedFile file = System.Web.HttpContext.Current.Request.Files.Get(filename);  //从browser传过来的的文件
16 
17                 if (file != null && file.ContentLength > 0)
18                 {
19                     //文件后缀名
20                     string fileExtension = Path.GetExtension(file.FileName).ToLower();
21 
22                     //获取文件名
23                     string fileName = DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_ffff");
24                     fileName += fileExtension;
25 
26                     Stream postStream = file.InputStream;
27                     byte[] bytes = new byte[postStream.Length];
28                     postStream.Read(bytes, 0, file.ContentLength);
29                     postStream.Seek(0, SeekOrigin.Begin);    //设置当前流的位置为流的开始 
30                     postStream.Close();
31 
32                     //写入本地
33                     var repath = UploadHelper.UploadFile(bytes, basePath, fileName);
34 
35                     result.Code = 0;
36                     result.Message = "OK";
37                     result.Data = repath;
38                 }
39                 return Json(JsonConvert.SerializeObject(result));
40             }
41             catch (Exception)
42             {
43                 return Json(JsonConvert.SerializeObject(result));
44             }
45         }
View Code

上传本地文件处理方法:UploadHelper.UploadFile()

 1         /// <summary>
 2         /// 上传文件到本地
 3         /// </summary>
 4         /// <param name="filename"></param>
 5         /// <param name="basePath"></param>
 6         /// <param name="bytes"></param>
 7         /// <returns></returns>
 8         public static string UploadFile(byte[] bytes,string basePath, string filename)
 9         {
10             string result = "";
11             try
12             {
13                 if (bytes != null)
14                 {
15                     //保存文件路径,比如:\Images\2020-01-01\,这里的basePath相当于\Images
16                     string upfilePath = basePath + "\" + DateTime.Now.ToString("yyyy-MM-dd") + "\";  //根路径
17                     //上传到本地  ~/表示上级目录,如果不加则表示同级目录
18                     string filePath = System.Web.HttpContext.Current.Server.MapPath("~/" + upfilePath);
19                     if (!Directory.Exists(filePath))
20                     {
21                         Directory.CreateDirectory(filePath);
22                     }
23                     //完整路径:项目目录\Images\2020-01-01\abc.jpg
24                     string fileSavePath = Path.Combine(filePath, filename);  //合并成完整的文件路径
25 
26                     //写入本地
27                     using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
28                     {
29                         fs.Write(bytes, 0, bytes.Length);
30                         fs.Close();
31                         fs.Dispose();
32                     }
33                     //返回路径:/Images/2020-01-01/abc.jpg
34                     result = (upfilePath + filename).Replace("\", "/");
35                 }
36                 else
37                 {
38                     result = "上传的文件信息不存在!";
39                 }
40             }
41             catch (Exception ex)
42             {
43                 return "";
44             }
45             return result;
46         }

一般向本地服务器上传的同时,还要向cdn服务器上传一份,请求cdn服务器接口代码如下:

 1         /// <summary>
 2         /// 上传文件到远程服务器
 3         /// </summary>
 4         /// <param name="bytes"></param>
 5         /// <param name="basepath"></param>
 6         /// <param name="filename"></param>
 7         /// <returns></returns>
 8         public static string PostUploadFile(byte[] bytes, string basepath, string filename)
 9         {
10             string repath = "";
11             string hosturl = ConfigurationManager.AppSettings["apihost"] ?? "https://cache.xxxxxx.com:8080/";    //远程服务器路径
12             try
13             {
14                 var apiurl = hosturl + "api/UpLoad/ReceiveFile";  //远程请求接口 相当于:https://cache.xxxxxx.com:8080/api/UpLoad/ReceiveFile
15                 HttpClient httpClient = HttpClientFactory.GetHttpClient();
16                 string upfilePath = basepath + "\" + DateTime.Now.ToString("yyyy-MM-dd") + "\";  //保存路径,比如:\Images\2020-01-01\,basepath相当于\Images
17                 using (var multipartFormDataContent = new MultipartFormDataContent())  //MultipartFormDataContent相当于 "Content-Type": "multipart/form-data"
18                 {
19                     //二进制流传输,远程服务器可以使用: Request.Files.Get("filedata")接收
20                     multipartFormDataContent.Add(new ByteArrayContent(bytes, 0, bytes.Length), "filedata", filename);
21                     //远程服务器可以使用: Request["filePath"]接收
22                     multipartFormDataContent.Add(new StringContent(upfilePath, Encoding.UTF8, "application/x-www-form-urlencoded"), "filePath");
23 
24                     //post请求
25                     var response = httpClient.PostAsync(apiurl, multipartFormDataContent).Result;
26                     if (response.StatusCode == System.Net.HttpStatusCode.OK)
27                     {
28                         var result = response.Content.ReadAsStringAsync().Result;
29                         if ((int)response.StatusCode == 200)
30                         {
31                             repath = (upfilePath + filename).Replace("\", "/");
32                         }
33                     }
34                 }
35                 return repath;
36             }
37             catch (Exception ex)
38             {
39                 return repath;
40             }
41         }

接下来看看在远程cdn服务器上如何接收本地服务器上传过来的文件,实际上跟本地服务上传没多大区别。

创建一个文件上传服务,比如创建一个WebApI服务,创建一个文件上传接口:/api/UpLoad/ReceiveFile,然后将该服务发布到IIS上即可

然后客户端请求路径:https://cache.xxxxxx.com:8080/api/UpLoad/ReceiveFile

 1     /// <summary>
 2     /// 文件上传服务
 3     /// </summary>
 4     public class UpLoadController : ApiController
 5     {
 6         /// <summary>
 7         /// 文件接收接口
 8         /// </summary>
 9         /// <returns></returns>
10         [HttpPost]
11         public HttpResponseMessage ReceiveFile()
12         {
13             HttpResponseMessage response = null;
14             try
15             {
16                 HttpPostedFile file = HttpContext.Current.Request.Files.Get("filedata");           //获取文件流
17                 string getfilepath = HttpContext.Current.Request["filePath"] ?? "\Images\";      //获取保存路径(不包含文件名),默认:\Images\
18                 var filename = file.FileName;   //获取文件名
19 
20                 //保存到本地的路径,~/表示指向上级根目录
21                 string savePath = HttpContext.Current.Server.MapPath("~/" + getfilepath);
22 
23                 //创建文件夹
24                 if (!Directory.Exists(savePath))
25                 {
26                     Directory.CreateDirectory(savePath);
27                 }
28 
29                 //保存文件到指定路径下
30                 string saveFilePath = Path.Combine(savePath, filename);
31                 Stream postStream = file.InputStream;
32                 using (FileStream fs = new FileStream(saveFilePath, FileMode.Create))
33                 {
34                     byte[] new_b = new byte[postStream.Length];
35                     while (postStream.Read(new_b, 0, new_b.Length) != 0)
36                     {
37                         fs.Write(new_b, 0, new_b.Length);
38                     }
39                     postStream.Close();
40                     fs.Close();
41                     fs.Dispose();
42                 }
43                 response = Request.CreateResponse(HttpStatusCode.OK);  //成功返回200
44             }
45             catch (Exception)
46             {
47                 response = Request.CreateResponse(HttpStatusCode.BadRequest); //返回400
48             }
49             return response;
50         }
51 
52     }
原文地址:https://www.cnblogs.com/peterzhang123/p/13524025.html