Cách kiểm thử API upload file (multipart/form-data) trong Apidog

Học cách kiểm thử API tải tệp lên trong Apidog: gửi các yêu cầu multipart/form-data, đính kèm một tệp, xác minh phản hồi và sửa lỗi đường dẫn trong Runner và CLI.

INEZA Felin-Michel

INEZA Felin-Michel

16 tháng 7 2026

Cách kiểm thử API upload file (multipart/form-data) trong Apidog

Apidog cho doanh nghiệp

Triển khai tại chỗ

SSO & RBAC

Tuân thủ SOC 2

Khám phá Apidog Enterprise

Bạn đã xây dựng một endpoint chấp nhận một tệp. Người dùng tải ảnh đại diện lên POST /avatars, hoặc ứng dụng của bạn đẩy một tệp PDF đã ký lên POST /documents. Tuyến đường này hoạt động trong đầu bạn. Giờ đây, bạn cần chứng minh rằng nó hoạt động qua HTTP: chọn một tệp thực, đính kèm nó vào một trường biểu mẫu, gửi yêu cầu và kiểm tra phản hồi.

Đây là lúc nhiều công cụ API trở nên phức tạp. Tải tệp sử dụng multipart/form-data, chứ không phải JSON, vì vậy bạn không thể dán toàn bộ nội dung và nhấn gửi. Bạn cần một trình tạo yêu cầu hiểu các trường tệp và một trình chạy thử nghiệm có thể tìm thấy tệp khi thử nghiệm chạy sau này. Apidog xử lý cả hai, và hướng dẫn này sẽ chỉ cho bạn toàn bộ quy trình: gửi một tệp tải lên đơn lẻ, gửi một tệp cùng với JSON, xác nhận phản hồi, và sau đó là phần trung thực mà không ai cảnh báo bạn, đó là điều gì sẽ xảy ra khi bước tải lên đó chạy ở chế độ không giao diện trong Runner hoặc CLI và không thể tìm thấy tệp. Nếu bạn muốn tìm hiểu nền tảng về định dạng trước, bài giới thiệu tải tệp trong API sẽ trình bày cách các yêu cầu multipart được cấu trúc. Tham khảo MDN về FormData là một tài liệu bổ trợ tốt cho phía trình duyệt.

button

multipart/form-data là gì và tại sao các tác vụ tải lên cần nó

Phần thân yêu cầu API có thể có nhiều dạng. Trong phần Body yêu cầu của Apidog, bạn có thể chọn form-data, x-www-form-urlencoded, JSON, XML, raw hoặc binary. Hầu hết thời gian bạn sẽ dùng JSON. Tải tệp là một ngoại lệ.

Loại body form-data ánh xạ tới tiêu đề Content-Type: multipart/form-data. Đây là định dạng được xây dựng để tải tệp lên cùng với các dữ liệu khác. Thay vì một khối dữ liệu duy nhất, phần thân được chia thành nhiều phần, mỗi phần có tên riêng và nội dung riêng. Một phần có thể là một chuỗi văn bản đơn giản như chú thích, một phần khác có thể là các byte thô của một hình ảnh. Đó là lý do tại sao một hình ảnh được tải lên và siêu dữ liệu của nó có thể được gửi trong cùng một yêu cầu.

Người họ hàng gần là x-www-form-urlencoded. Nó trông tương tự trong trình chỉnh sửa, các cặp khóa-giá trị được gửi trong phần thân, nhưng nó dành cho các biểu mẫu đơn giản không có tệp. Nếu endpoint của bạn chấp nhận một tệp, form-data là thứ bạn muốn. Chỉ sử dụng x-www-form-urlencoded khi mọi trường đều là một giá trị vô hướng ngắn và không liên quan đến byte.

Trong form-data, Apidog hiển thị mỗi tham số dưới dạng một cặp khóa-giá trị, và mỗi tham số mang một kiểu: chuỗi (string), số nguyên (integer), tệp (file), v.v. Kiểu dữ liệu cho từng tham số chính là điểm mấu chốt. Đặt một trường thành file và Apidog sẽ coi giá trị của nó là một tệp để đính kèm thay vì văn bản để gửi.

Gửi một tệp tải lên duy nhất và xác nhận phản hồi

Giả sử bạn đang kiểm thử POST /avatars. Nó nhận một trường, avatar, chứa một hình ảnh và trả về JSON với URL đã lưu trữ. Đây là hướng dẫn chi tiết.

1. Mở phần Body và chọn form-data. Trong endpoint hoặc một yêu cầu mới của bạn, đặt phương thức là POST và URL là tuyến đường avatars của bạn. Mở tab Body và chọn loại body form-data. Apidog sẽ tự động đặt Content-Type: multipart/form-data cho bạn.

2. Thêm tham số tệp và đặt kiểu của nó thành file. Thêm một tham số với khóa avatar. Bên cạnh khóa, sử dụng bộ chọn kiểu để thay đổi kiểu của nó từ string thành file. Ô giá trị sẽ biến thành công cụ chọn tệp thay vì hộp văn bản.

3. Nhấp vào Upload và chọn một tệp cục bộ. Nhấp vào Upload trên hàng avatar và chọn một hình ảnh từ máy của bạn, chẳng hạn jane-profile.png. Apidog sẽ ghi lại đường dẫn đến tệp đó.

4. Gửi yêu cầu. Nhấn Gửi. Apidog đọc tệp từ đường dẫn cục bộ đã lưu trữ, xây dựng phần thân multipart và gửi nó. Điều đáng biết trước: Apidog gửi tệp trong yêu cầu nhưng không lưu trữ tệp trên đám mây. Nó chỉ lưu đường dẫn cục bộ, không phải các byte. Chi tiết đó quan trọng sau này, vì vậy hãy ghi nhớ nó.

Một cuộc gọi thành công sẽ trả về kết quả như sau:

{
  "id": "usr_8842",
  "avatarUrl": "https://cdn.example.com/avatars/usr_8842.png",
  "sizeBytes": 48210,
  "contentType": "image/png"
}

5. Xác nhận phản hồi. Một yêu cầu gửi thành công trả về 200 tự nó chưa phải là một bài kiểm tra đạt. Thêm các xác nhận để kiểm tra thực sự có ý nghĩa. Trong Apidog, bạn thêm chúng dưới dạng xác nhận sau yêu cầu (post-request assertions) trên endpoint hoặc bước kịch bản. Nói một cách đơn giản, bạn muốn xác nhận trạng thái và rằng phần thân chứa một URL có thể sử dụng được:

status code == 200
$.avatarUrl exists
$.contentType == "image/png"

Những điều này ánh xạ trực tiếp đến giao diện người dùng xác nhận của Apidog: một xác nhận về mã trạng thái, một xác nhận về sự hiện diện của JSONPath $.avatarUrl, một xác nhận về $.contentType. Nếu bạn mới làm quen với các xác nhận, hướng dẫn xác nhận API sẽ trình bày đầy đủ các toán tử và cách JSONPath nhắm mục tiêu một trường.

Để kiểm tra nhanh bên ngoài công cụ, việc tải lên tương tự trong curl sẽ trông như thế này:

curl -X POST https://api.example.com/avatars \
  -F "avatar=@jane-profile.png"

Cờ -F là cách curl xây dựng một phần multipart, và @ cho nó biết để đọc nội dung tệp. Tham số tệp form-data của Apidog cũng làm điều tương tự với một công cụ chọn thay vì một cờ.

Gửi một tệp và JSON cùng nhau

Các endpoint thực tế hiếm khi chỉ nhận một tệp trần. POST /documents có thể muốn tệp kèm theo siêu dữ liệu: một tiêu đề, một danh mục, có thể là một mảng thẻ. Bạn có hai cách rõ ràng để thực hiện điều này trong một yêu cầu multipart.

Trường hợp đơn giản là các trường vô hướng (scalar fields). Thêm các tham số form-data khác bên cạnh trường tệp của bạn và để chúng ở dạng string hoặc integer. Một chuỗi title, một chuỗi category, một file được đặt kiểu file. Cả ba đều được gửi trong cùng một yêu cầu.

Khi siêu dữ liệu có cấu trúc, như một đối tượng lồng nhau hoặc một mảng, bạn gửi nó dưới dạng JSON bên trong một phần chuỗi. Thêm một tham số form-data có tên metadata, giữ kiểu của nó là string và dán JSON trực tiếp vào giá trị:

{
  "title": "Q3 Invoice",
  "category": "billing",
  "tags": ["invoice", "2026", "paid"]
}

Vì vậy, yêu cầu có hai phần: file (kiểu file) chứa q3-invoice.pdf, và metadata (kiểu string) chứa JSON đó. Máy chủ đọc tệp từ một phần và phân tích cú pháp JSON từ phần còn lại. Nhiều API công khai chấp nhận tải lên theo cách chính xác này; tài liệu tải tệp của Stripe là một ví dụ điển hình về một endpoint multipart thực tế ghép một phần tệp với các trường dữ liệu đơn giản. Mẫu này đủ phổ biến đến mức người dùng Postman cũng gặp phải; nếu bạn đang di chuyển, hướng dẫn về tải tệp và dữ liệu JSON trong Postman ánh xạ rõ ràng sang các trường form-data của Apidog.

Cần đính kèm nhiều hơn một tệp? Thêm một tham số khác với kiểu file. Một yêu cầu POST /documents chấp nhận một tệp chính và một hình thu nhỏ sẽ có hai hàng tệp, file và thumbnail, mỗi hàng có nút Upload riêng. Không có chế độ đa tệp đặc biệt nào; bạn chỉ cần thêm các tham số kiểu tệp cho đến khi bạn đã bao gồm mọi phần mà endpoint mong đợi.

Biến yêu cầu thành một kịch bản kiểm thử có thể lặp lại

Một lần gửi duy nhất chứng tỏ endpoint hoạt động một lần. Để phát hiện lỗi hồi quy, bạn muốn tải lên bên trong một kịch bản kiểm thử đã lưu, chạy theo yêu cầu hoặc theo lịch trình. Chuỗi các bước: tải lên ảnh đại diện, lấy id được trả về, sau đó gọi GET /users/{id} và xác nhận URL ảnh đại diện đã được lưu.

Xây dựng điều này theo cách tương tự như bạn đã xây dựng yêu cầu đơn lẻ, sau đó lưu nó dưới dạng một bước trong kịch bản. Hướng dẫn cách viết kịch bản kiểm thử với Apidog bao gồm việc xâu chuỗi các bước và truyền giá trị giữa các bước. Khi tác vụ tải lên nằm trong một kịch bản, bạn có thể chạy nó trên môi trường staging sau mỗi lần triển khai, thêm các nhánh điều kiện với logic điều kiện trong các kịch bản kiểm thử API, hoặc đặt nó theo thời gian với các bài kiểm thử API theo lịch trình.

Mọi thứ ở trên đều chạy tốt trên máy của bạn, vì máy của bạn có tệp. Giả định đó chính xác là điều sẽ bị phá vỡ tiếp theo.

Cái bẫy: các tác vụ tải lên chạy ở nơi khác

Đây là phần mà con đường vui vẻ che giấu. Apidog lưu trữ đường dẫn tệp, chứ không phải tệp. Trên máy tính xách tay của bạn, điều đó không thể thấy được, bởi vì đường dẫn luôn phân giải đến một tệp thực. Khoảnh khắc cùng một bước đó chạy trên một máy khác, đường dẫn sẽ không trỏ đến đâu cả.

Bạn sẽ gặp trường hợp này ở hai nơi.

Hợp tác nhóm. Khi một đồng đội mở yêu cầu POST /avatars của bạn, họ sẽ thấy tham số tệp và đường dẫn bạn đã chọn, ví dụ /Users/jane/pics/jane-profile.png. Họ có thể thấy yêu cầu, nhưng họ không thể gửi nó, bởi vì tệp đó nằm trên ổ đĩa của bạn, không phải của họ. Đường dẫn là cục bộ đối với máy đã chọn nó.

Chạy trên Runner và CLI. Đây là vấn đề thường gặp trong tự động hóa. Kịch bản tải lên của bạn vượt qua kiểm tra cục bộ, bạn lên lịch nó trong Runner hoặc chạy từ CLI, và bước tải tệp thất bại. Không có gì sai với các xác nhận của bạn. Runner chỉ đơn giản là không thể tìm thấy tệp tại đường dẫn mà máy tính xách tay của bạn đã lưu, bởi vì đường dẫn đó không tồn tại trên máy chủ của runner.

Giải pháp xuất phát từ nguyên nhân. Tệp phải tồn tại trên máy đang thực hiện gửi, và đường dẫn của bước phải trỏ đến tệp đó ở đó.

Đối với Runner: Runner đọc tệp từ một thư mục máy chủ (host directory) được gắn kết (mounted) vào volume của nó. Bạn thiết lập việc gắn kết đó khi triển khai Runner, sử dụng cờ -v. Sao chép tệp tải lên của bạn vào thư mục máy chủ đã gắn kết đó. Sau đó, mở chi tiết bước tải tệp trong kịch bản, nhấp vào nút Batch Edit ở góc trên cùng bên phải và thay thế giá trị của trường tệp bằng đường dẫn bên trong thư mục của Runner, ví dụ:

/opt/runner/jane-profile.png

Đối với CLI: tương tự. Đặt tệp trên máy CLI, sau đó sử dụng Batch Edit trên bước để trỏ đường dẫn đến vị trí của nó ở đó, ví dụ:

/opt/apidog/runner/jane-profile.png

Sạch hơn việc mã hóa cứng: sử dụng biến. Thay vì ghim một đường dẫn cố định trong bước, hãy thay thế giá trị bằng một biến và đặt giá trị của biến thành đường dẫn tệp thực tế cho từng môi trường. Khi đó, cùng một kịch bản sẽ chạy trên máy tính xách tay của bạn, Runner và CI mà không cần chỉnh sửa bước mỗi lần. Bạn trỏ biến đến /Users/jane/pics/jane-profile.png cục bộ và /opt/runner/jane-profile.png trên runner, và bản thân bước đó không bao giờ thay đổi.

Một điều kiện tiên quyết đáng được nêu rõ: Runner chỉ có thể truy cập các tệp máy chủ nằm trong thư mục mà bạn đã gắn kết với cờ -v tại thời điểm triển khai. Nếu tệp của bạn không nằm trong vùng gắn kết đó, sẽ không có đường dẫn nào tìm thấy nó. Đó là một chi tiết thiết lập triển khai, không phải giới hạn của kế hoạch. Tài liệu Apidog về các yêu cầu tải tệp giải thích chi tiết các bước gắn kết và chỉnh sửa hàng loạt nếu bạn muốn xem phiên bản chính thức.

Tự động hóa quy trình với Apidog CLI

Sau khi kịch bản tải lên của bạn được lưu, bạn có thể chạy nó không giao diện (headless) trong CI. Cài đặt CLI và xác thực:

npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>

Sau đó chạy kịch bản đã lưu theo ID, trỏ nó đến một môi trường:

apidog run --access-token $APIDOG_ACCESS_TOKEN -t <scenario_id> -e <env_id> -r cli

Ở đây -t là ID kịch bản kiểm thử, -e là ID môi trường, và -r là trình báo cáo (sử dụng cli, html, hoặc junit, cách nhau bằng dấu phẩy cho nhiều tùy chọn). CLI chạy các kịch bản đã lưu của bạn từ dự án đám mây và báo cáo pass/fail bằng mã thoát (exit codes), điều này cho phép nó kiểm soát một pipeline. Chi tiết thiết lập nằm trong hướng dẫn cài đặt Apidog CLI.

Một lưu ý trung thực, và đó cũng là lưu ý từ phần trước: một kịch bản có bước tải tệp cần tệp đó phải có mặt trên máy CLI, và đường dẫn của bước phải trỏ đến nó ở đó. Đặt tệp trên runner, sau đó Batch Edit đường dẫn (hoặc sử dụng một biến) trước khi chạy. Bỏ qua điều đó và bước tải lên sẽ không tìm thấy tệp mặc dù phần còn lại của kịch bản vẫn ổn. Để thiết lập CI đầy đủ hơn, bao gồm việc truyền các đầu vào theo từng hàng, hãy xem kiểm thử dựa trên dữ liệu với Apidog CLI.

Câu hỏi thường gặp (FAQ)

Tại sao đồng đội của tôi không thể gửi yêu cầu tải tệp của tôi? Apidog lưu trữ đường dẫn tệp cục bộ, chứ không phải bản thân tệp, và nó không bao giờ tải tệp lên đám mây. Đồng đội của bạn thấy yêu cầu và đường dẫn bạn đã chọn, nhưng đường dẫn đó giải quyết thành một tệp trên ổ đĩa của bạn, không phải của họ. Hãy yêu cầu họ đặt một bản sao của tệp trên máy của họ và trỏ trường đó vào đường dẫn của riêng họ. Cơ chế tương tự giải thích tại sao các bài kiểm thử theo lịch trình và các tác vụ Runner cần tệp được chuẩn bị sẵn ở nơi chúng chạy.

Làm cách nào để gửi JSON cùng với một tệp trong cùng một yêu cầu? Giữ loại body là form-data. Thêm trường tệp của bạn với kiểu file, sau đó thêm một tham số khác với kiểu string và dán JSON vào giá trị của nó. Máy chủ nhận cả hai phần trong một yêu cầu multipart: tệp trong một phần, chuỗi JSON trong phần khác. Đây là cách chuẩn để đính kèm siêu dữ liệu vào một tác vụ tải lên.

Tôi nên sử dụng đường dẫn nào cho tệp trong Runner? Sử dụng đường dẫn bên trong thư mục máy chủ mà bạn đã gắn kết vào volume của Runner bằng cờ -v tại thời điểm triển khai, ví dụ /opt/runner/yourfile.jpg. Sao chép tệp vào thư mục đã gắn kết đó, sau đó mở bước, nhấp vào Batch Edit và đặt giá trị của trường thành đường dẫn đó. Tương đương với CLI sẽ trông giống như /opt/apidog/runner/yourfile.jpg.

Có giới hạn kích thước tệp hoặc danh sách loại tệp được phép không? Hành vi tải lên trong Apidog là về cách yêu cầu được xây dựng và nơi tệp được đọc từ đó. Giới hạn thực tế của bạn về kích thước và loại tệp đến từ API bạn đang kiểm thử, vì vậy hãy kiểm tra các quy tắc xác thực của máy chủ của bạn và viết các xác nhận dựa trên các phản hồi mà nó trả về cho các tệp quá khổ hoặc bị từ chối.

Tôi nên sử dụng form-data hay x-www-form-urlencoded cho việc tải lên? Sử dụng form-data. Nó ánh xạ tới multipart/form-data và được xây dựng để mang tệp. x-www-form-urlencoded dành cho các biểu mẫu đơn giản gồm các trường vô hướng ngắn không có tệp, vì vậy nó sẽ không mang hình ảnh hoặc tệp PDF của bạn.

Tóm tắt

Kiểm thử tải tệp tóm lại ở hai điều: xây dựng yêu cầu multipart đúng cách và đảm bảo tệp có thể truy cập được ở bất cứ đâu bài kiểm thử chạy. Trong Apidog, bạn đặt Body là form-data, chuyển kiểu trường của bạn thành file, nhấp vào Upload, thêm bất kỳ JSON nào dưới dạng một phần chuỗi, sau đó gửi và xác nhận. Khi bạn chuyển cùng một kịch bản sang Runner hoặc CLI, hãy chuẩn bị tệp trên máy đó và điều chỉnh lại đường dẫn bằng Batch Edit hoặc một biến, và quá trình chạy tự động sẽ hoạt động giống như trên máy cục bộ của bạn.

Muốn thử nghiệm nó với endpoint của riêng bạn? Tải Apidog, trỏ một yêu cầu form-data đến tuyến đường tải lên của bạn, và xem phản hồi trở lại. Bắt đầu miễn phí, không yêu cầu thẻ tín dụng.

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API