c# - 我如何在上傳檔案的同時發送簡單的 JSON 資料?
我正在嘗試在 ServiceStack TypeScript 客戶端中設置一個文件上傳請求,該請求還包含該文件相關的月份。我該如何設置請求,以便兩者都能傳到服務器?
我已經嘗試過各種更改,包括手動更改標頭以嘗試強制 Content-Type 為 application/json,但這沒有用(但我懷疑即使有效,也會破壞文件上傳)。
客戶端 API:
export const serviceApi = {
importData: (month: string, file: File) => {
var client = new JsonServiceClient("");
var request = new DTOs.ImportData();
// At this point, the month has a value
request.month = month.replace('/', '-').trim();
let formData = new FormData();
formData.append('description', file.name);
formData.append('type', 'file');
formData.append('file', file);
const promise = client.postBody(request, formData);
return from(promise);
},
};
DTO 定義:
[Route("/api/data/import/{Month}", "POST")]
public class ImportData : IReturn<ImportDataResponse>
{
public string Month { get; set; }
}
public class ImportDataResponse : IHasResponseStatus
{
public ResponseStatus ResponseStatus { get; set; }
}
伺服器端 API:
[Authenticate]
public object Post(ImportData request)
{
if (Request.Files == null || Request.Files.Length <= 0)
{
throw new Exception("No import file was received by the server");
}
// This is always coming through as null
if (request.Month == null)
{
throw new Exception("No month was received by the server");
}
var file = (HttpFile)Request.Files[0];
var month = request.Month.Replace('-', '/');
ImportData(month, file);
return new ImportDataResponse();
}
我可以看到檔案在伺服器端正確傳送過來,而且我可以看到一個 HTTP 請求通過,查詢字串參數中的月份設定為 "07-2019",但是當我在伺服器端的 API 函數中中斷時,請求的 month 屬性為 null。
更新,這裡是 HTTP 請求/回應標頭:
請求標頭
POST /json/reply/ImportData?month=07-2019 HTTP/1.1
Host: localhost:40016
Connection: keep-alive
Content-Length: 7366169
Origin: http://localhost:40016
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryI8CWlbw4tP80PkpZ
Accept: */*
Referer: http://localhost:40016/data
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: _ga=GA1.1.673673009.1532913806; ASP.NET_SessionId=gtwdk3wsvdn0yulhxyblod3g; __utmc=111872281; __utmz=111872281.1533684260.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); ss-opt=perm; __utma=111872281.673673009.1532913806.1550789161.1550794391.20; _gid=GA1.1.893581387.1558389301; ss-id=kfq4G0GYb3WldSdCaRyJ; ss-pid=aZ400sqM4n3TQgNVnHS2
回應標頭
HTTP/1.1 500 Exception
Cache-Control: private
Content-Type: application/json; charset=utf-8
Vary: Accept
Server: Microsoft-IIS/10.0
X-Powered-By: ServiceStack/5.10 NET45 Win32NT/.NET
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RTpcVEZTXFNvdXJjZVxNZWRpc2VuXFdlYnNpdGVzXE9OaWlDU1xNYWluXFNvdXJjZVxPbmlpY3NSZWFjdC1QYXltZW50c1xPbmlpY3NSZWFjdFxPbmlpY3NSZWFjdFxqc29uXHJlcGx5XEltcG9ydE1CU0NvZGVz?=
X-Powered-By: ASP.NET
Date: Tue, 21 May 2019 21:49:03 GMT
Content-Length: 605
查詢字串參數
month=07-2019
答案#1
你將能夠使用 JavaScript 的 fetch API 直接上傳檔案,例如:
let formData = new FormData();
formData.append('description', file.name);
formData.append('type', 'file');
formData.append('file', file);
fetch('/api/data/import/07-2019', {
method: 'POST',
body: formData
});
否則,如果你想使用 ServiceStack 的 TypeScript JsonServiceClient,你需要使用允許你將請求 DTO 與單獨的請求主體一起發送的 API,例如:
formData.append('month', '07-2019');
client.postBody(new ImportData(), formData);
答案#2
我覺得月份不應該作為請求標頭的一部分,那有點不尋常。它應該是表單資料的一部分。
如果你做了:
formData.append('Month', month.replace('/', '-').trim());
在客戶端,然後 request.Month 或 request.content.Month 應該可以使用,這取決於在你的實例中請求對象是如何處理的。
