在 RESTful Web 服務中下載和上傳檔案 - mscharhag
通常我們使用標準的資料交換格式,如 JSON 或 XML 與 REST web 服務。然而,許多 REST 服務至少有一些操作很難僅用 JSON 或 XML 來完成。例如上傳產品圖片、使用上傳的 CSV 檔案匯入資料或生成可下載的 PDF 報告。
在這篇文章中,我們關注那些通常被歸類為檔案下載和上傳的操作。這有點不穩定,因為傳送簡單的 JSON 文件也可以看作是 (JSON) 檔案上傳操作。
一個常見的錯誤是關注操作所需的特定檔案格式。相反,我們應該考慮我們想要表達的操作。檔案格式僅決定用於操作的媒體型別。
例如,假設我們要設計一個 API,讓使用者將頭像圖片上傳到他們的使用者帳戶。
在這裡,出於各種原因,將頭像影像與使用者帳戶資源分開通常是一個好主意:
- 頭像影像不太可能改變,因此它可能是快取的一個很好的候選者。另一方面,使用者帳戶資源可能包含諸如上次登入日期之類的經常更改的內容。
- 並非所有訪問使用者帳戶的客戶端都可能對頭像影像感興趣。因此,可以節省頻寬。
- 對於客戶端來說,通常最好單獨載入影像(想想使用<img>標籤的 Web 應用程式)
可以透過以下方式訪問使用者帳戶資源:
/users/<使用者 ID> |
我們可以想出一個代表頭像影像的簡單子資源:
/users/<user-id>/avatar |
上傳頭像是一個簡單的替換操作,可以透過 PUT 表示:
PUT /users/<user-id>/avatar Content-Type: image/jpeg <image data> |
如果使用者想要刪除他的頭像,我們可以使用簡單的 DELETE 操作:
DELETE /users/<user-id>/avatar |
當然,客戶需要一種顯示頭像的方法。因此,我們可以使用 GET 提供下載操作:
GET /users/<user-id>/avatar |
返回:
HTTP/1.1 200 Ok Content-Type: image/jpeg <image data> |
在這個簡單的例子中,我們使用了一個帶有常見更新、刪除、獲取操作的新子資源。唯一的區別是我們使用影像媒體型別而不是 JSON 或 XML。
讓我們看一個不同的例子。
假設我們提供了一個 API 來管理產品資料。我們希望透過一個選項來擴充套件此 API,以從上傳的 CSV 檔案中匯入產品。我們應該考慮一種表達產品匯入操作的方法,而不是考慮檔案上傳。
可能最簡單的方法是將 POST 請求傳送到單獨的資源:
POST /product-import Content-Type: text/csv <csv data> |
或者,我們也可以將其視為產品的批次操作。正如我們在另一篇關於REST 批次操作的文章中瞭解到的,PATCH 方法是一種表達對集合的批次操作的可能方式。在這種情況下,TEXT/CSV 描述了對產品集合的期望更改。
PATCH /products Content-Type: text/csv action,id,name,price create,,Cool Gadget,3.99 create,,Nice cap,9.50 delete,42,, |
此示例建立兩個新產品並刪除 id 為42的產品。
處理檔案上傳可能需要相當長的時間。所以考慮將其設計為非同步 REST 操作。
混合檔案和後設資料
在某些情況下,我們可能需要將額外的後設資料附加到檔案中。例如,假設我們有一個 API,使用者可以在其中上傳假日照片。除了實際的影像資料,照片還可能包含描述、拍攝地點等。
在這裡,我會(再次)推薦使用兩個單獨的操作,原因與上一節中關於頭像影像的原因類似。即使這裡的情況有點不同(資料直接連結到影像),它通常也是更簡單的方法。
在這種情況下,我們可以首先透過傳送實際影像來建立照片資源:
POST /photos Content-Type: image/jpeg <image data> |
響應:
HTTP/1.1 201 Created Location: /photos/123 |
之後,我們可以將額外的後設資料附加到照片中:
PUT /photos/123/metadata Content-Type: application/json { "description": "Nice shot of a beach in hawaii", "location": "hawaii", "filename": "hawaii-beach.jpg" } |
當然,我們也可以反過來設計,在影像之前傳送後設資料。
在 JSON 或 XML 中嵌入 Base64 編碼的檔案
如果無法在單獨的請求中拆分檔案內容和後設資料,我們可以使用Base64 編碼將檔案嵌入到 JSON/XML 文件中。使用 Base64 編碼,我們可以將二進位制格式轉換為文字表示,該文字表示可以整合到其他基於文字的格式中,例如 JSON 或 XML。
示例請求可能如下所示:
POST /photos Content-Type: application/json { "width": "1280", "height": "920", "filename": "funny-cat.jpg", "image": "TmljZSBleGFt...cGxlIHRleHQ= " } |
將媒體型別與多部分請求混合
在單個請求/響應中傳輸影像資料和後設資料的另一種可能方法是多部分媒體型別。
多部分媒體型別需要一個邊界引數,用作不同正文部分之間的分隔符。以下請求由兩個正文部分組成。第一個包含影像,而第二個部分包含後設資料。
例如
POST /photos Content-Type: multipart/mixed; boundary=foobar --foobar Content-Type: image/jpeg <image data> --foobar Content-Type: application/json { "width": "1280", "height": "920", "filename": "funny-cat.jpg" } --foobar-- |
不幸的是,多部分請求/響應通常很難處理。例如,並非每個 REST 客戶端都能夠構建這些請求,並且很難在單元測試中驗證響應。
相關文章
- 搭建 Restful Web 服務RESTWeb
- 轉享:Ehcache 服務和RESTful Web ServicesRESTWeb
- 檔案上傳和下載功能
- Node.js:上傳檔案,服務端如何獲取檔案上傳進度Node.js服務端
- ASP.NET中下載檔案ASP.NET
- Java Web 檔案上傳JavaWeb
- WEB漏洞——檔案上傳Web
- RESTFul Web Api 服務框架(一)RESTWebAPI框架
- 【SpringBoot】使用RestTemplate在服務之間進行MultipartFile格式檔案的傳遞【檔案上傳】Spring BootREST
- Xshell在Windows和Linux間檔案的上傳和下載WindowsLinux
- 檔案上傳下載
- Web安全-檔案上傳漏洞Web
- Web安全之檔案上傳Web
- WEB安全:檔案上傳漏洞Web
- 分散式檔案上傳導致服務假死了?分散式
- 單個檔案上傳和批量檔案上傳
- yii2 restful web服務路由RESTWeb路由
- Yii2.0 RESTful Web服務(3)RESTWeb
- Yii2.0 RESTful Web服務(4)RESTWeb
- 第19章 建立RESTful Web服務RESTWeb
- 使用 Jersey 和 Apache Tomcat 構建 RESTful Web 服務ApacheTomcatRESTWeb
- spring cloud feign 檔案上傳和檔案下載SpringCloud
- springCloud 微服務通過minio實現檔案上傳和檔案下載介面SpringGCCloud微服務
- 如何在ASP.NET中下載檔案ASP.NET
- 檔案上傳與下載
- JAVA檔案上傳下載Java
- Vertx 檔案上傳下載
- centos上傳下載檔案CentOS
- <web滲透-檔案上傳漏洞>Web
- 在Oracle中存取BLOB物件實現檔案的上傳和下載Oracle物件
- 前端實現檔案下載和拖拽上傳前端
- SpringMVC中的檔案上傳和下載SpringMVC
- Java Struts檔案上傳和下載詳解Java
- 基於servlet的檔案上傳和下載Servlet
- Java SE 檔案上傳和檔案下載的底層原理Java
- java上傳檔案跟批量下載檔案Java
- SpringCloudGateway閘道器服務實現檔案上傳功能SpringGCCloudGateway
- Spring MVC 檔案上傳、Restful、表單校驗框架SpringMVCREST框架