<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Loading

      基于.NetCore開發博客項目 StarBlog - (25) 圖片接口與文件上傳

      前言

      上傳文件的接口設計有兩種風格,一種是整個項目只設置一個接口用來上傳,然后其他需要用到文件的地方,都只存一個引用ID;另一種是每個需要文件的地方單獨管理各自的文件。這倆各有優劣吧,本項目中選擇的是后者的風格,文章圖片和照片模塊又要能CRUD又要批量導入,還是各自管理文件比較好。

      圖片接口

      說會正題,先介紹一下圖片相關接口。

      圖片列表

      首先CRUD是肯定有的,圖片列表的分頁查看也是有的,不過因為篩選功能沒有做,所以就不定義一個ViewModel作為參數了。

      控制器代碼 StarBlog.Web/Apis/Blog/PhotoController.cs

      [HttpGet]
      public ApiResponsePaged<Photo> GetList(int page = 1, int pageSize = 10) {
          var paged = _photoService.GetPagedList(page, pageSize);
          return new ApiResponsePaged<Photo> {
              Pagination = paged.ToPaginationMetadata(),
              Data = paged.ToList()
          };
      }
      

      跟博客前臺公用一套圖片列表邏輯,所以這部分抽出來放在service,代碼如下

      StarBlog.Web/Services/PhotoService.cs

      public IPagedList<Photo> GetPagedList(int page = 1, int pageSize = 10) {
          return _photoRepo.Select.OrderByDescending(a => a.CreateTime)
              .ToList().ToPagedList(page, pageSize);
      }
      

      單個圖片

      獲取單個圖片,跟獲取文章的差不多,傳入ID,找不到就返回404,找到就返回圖片對象

      [HttpGet("{id}")]
      public ApiResponse<Photo> Get(string id) {
          var photo = _photoService.GetById(id);
          return photo == null
              ? ApiResponse.NotFound($"圖片 {id} 不存在")
              : new ApiResponse<Photo> {Data = photo};
      }
      

      圖片縮略圖

      在本系列第20篇中,本項目已經實現了圖片顯示的優化,詳見:基于.NetCore開發博客項目 StarBlog - (20) 圖片顯示優化

      除了 ImageSharp 組件提供的圖片縮略圖功能外,我這里還寫了另一個生成縮略圖的方法,這個方法有倆特點

      • 直接在內存中生成返回,不會寫入緩存文件
      • 生成的是Progressive JPEG格式,目前 ImageSharp 是不支持的,可以優化前端的加載速度

      控制器代碼

      [HttpGet("{id}/Thumb")]
      public async Task<IActionResult> GetThumb(string id, [FromQuery] int width = 300) {
          var data = await _photoService.GetThumb(id, width);
          return new FileContentResult(data, "image/jpeg");
      }
      

      service代碼

      /// <summary>
      /// 生成Progressive JPEG縮略圖 (使用 MagickImage)
      /// </summary>
      /// <param name="width">設置為0則不調整大小</param>
      public async Task<byte[]> GetThumb(string id, int width = 0) {
          var photo = await _photoRepo.Where(a => a.Id == id).FirstAsync();
          using (var image = new MagickImage(GetPhotoFilePath(photo))) {
              image.Format = MagickFormat.Pjpeg;
              if (width != 0) {
                  image.Resize(width, 0);
              }
      
              return image.ToByteArray();
          }
      }
      

      這個 MagickImage 是用 C++ 寫的,在不同平臺上引用不同 native 庫,需要在 csproj 里面寫上配置,這樣發布的時候才會帶上對應的依賴庫,而且似乎在 CentOS 系統上會有坑…

      <!--  復制 Magick 庫  -->
      <PropertyGroup>
          <MagickCopyNativeWindows>true</MagickCopyNativeWindows>
          <MagickCopyNativeLinux>true</MagickCopyNativeLinux>
          <MagickCopyNativeMacOS>true</MagickCopyNativeMacOS>
      </PropertyGroup>
      

      其他接口

      還有一些接口,跟之前介紹的大同小異,再重復一次也意義不大,讀者有需要的話可以自行查看源碼。

      圖片文件上傳

      這個同時也是圖片的添加接口

      先定義DTO

      public class PhotoCreationDto {
          /// <summary>
          /// 作品標題
          /// </summary>
          [Required(ErrorMessage = "作品標題不能為空")]
          public string Title { get; set; }
      
          /// <summary>
          /// 拍攝地點
          /// </summary>
          [Required(ErrorMessage = "拍攝地點不能為空")]
          public string Location { get; set; }
      }
      

      控制器代碼

      [Authorize]
      [HttpPost]
      public ApiResponse<Photo> Add([FromForm] PhotoCreationDto dto, IFormFile file) {
          var photo = _photoService.Add(dto, file);
      
          return !ModelState.IsValid
              ? ApiResponse.BadRequest(ModelState)
              : new ApiResponse<Photo>(photo);
      }
      

      因為上傳的同時還要附帶一些數據,需要使用 FormData 傳參,所以這里使用 [FromForm] 特性標記這個 dto 參數

      IFormFile 類型的參數可以拿到上傳上來的文件

      下面是service代碼

      public Photo Add(PhotoCreationDto dto, IFormFile photoFile) {
          var photoId = GuidUtils.GuidTo16String();
          var photo = new Photo {
              Id = photoId,
              Title = dto.Title,
              CreateTime = DateTime.Now,
              Location = dto.Location,
              FilePath = Path.Combine("photography", $"{photoId}.jpg")
          };
      
          var savePath = Path.Combine(_environment.WebRootPath, "media", photo.FilePath);
      	
          // 如果超出最大允許的大小,則按比例縮小
          const int maxWidth = 2000;
          const int maxHeight = 2000;
          using (var image = Image.Load(photoFile.OpenReadStream())) {
              if (image.Width > maxWidth)
                  image.Mutate(a => a.Resize(maxWidth, 0));
              if (image.Height > maxHeight)
                  image.Mutate(a => a.Resize(0, maxHeight));
              image.Save(savePath);
          }
      
          // 保存文件
          using (var fs = new FileStream(savePath, FileMode.Create)) {
              photoFile.CopyTo(fs);
          }
      
          // 讀取圖片的尺寸等數據
          photo = BuildPhotoData(photo);
      
          return _photoRepo.Insert(photo);
      }
      

      這里對圖片做了一些處理,拋開這些細節,其實對上傳的文件,最關鍵的只有幾行保存代碼

      using (var fs = new FileStream("savePath", FileMode.Create)) {
          photoFile.CopyTo(fs);
      }
      

      這樣就完成了文件上傳接口。

      系列文章

      posted @ 2022-12-22 23:35  程序設計實驗室  閱讀(986)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品一区二区美女| 峨边| 国内熟妇人妻色在线视频| 亚洲天堂一区二区三区四区| 日本熟妇色xxxxx日本免费看| 国产精品一区二区三区黄| 国产精品无遮挡在线观看| 最新日韩精品视频在线| 久9re热视频这里只有精品免费| 久久一级黄色大片免费观看| 久久一区二区中文字幕| 九九热在线精品视频九九| 人妻人人做人碰人人添| 老司机亚洲精品一区二区| 国产精品一区在线蜜臀| 日韩熟女精品一区二区三区| 色94色欧美sute亚洲线路二| 男人狂桶女人高潮嗷嗷| 国产欧美精品一区aⅴ影院| 亚洲国产成人久久综合区| 激情国产一区二区三区四区| 国产suv精品一区二区四| 内射极品少妇xxxxxhd| 午夜福利电影| 777奇米四色成人影视色区| 全黄h全肉边做边吃奶视频| 精品嫩模福利一区二区蜜臀| 精品不卡一区二区三区| 耒阳市| 亚洲免费视频一区二区三区| 一本无码人妻在中文字幕免费| 日韩东京热一区二区三区| 国产精品麻豆中文字幕| 亚洲欧美日韩愉拍自拍美利坚| 精品国产乱码久久久久APP下载| 亚洲欧美中文日韩v在线97| 日韩有码中文字幕一区二区| 无码人妻丰满熟妇区bbbbxxxx| 一本久道久久综合中文字幕| 久久亚洲私人国产精品| 蜜臀av无码一区二区三区|