如何在文件流上设置文件类型
How to set FileType on filestream
我正在尝试将文件流从 c# 发送到我的 js 后端。名称和路径已正确发送,但当我记录进入我的后端的文件时,类型似乎丢失了,我绝对需要文件类型,但我不知道如何传递它。有人可以帮我解决这个问题吗?
进来的对象:
File {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
size: 13920,
path: '/var/folders/5g/f343vctd6hd7smyd5ybnfp4m0000gn/T/upload_4aebdbbee06344e12d8566dd706fd1e6',
name: 'Invoice19.pdf',
type: null,
hash: null,
lastModifiedDate: 2020-03-17T14:11:04.812Z,
_writeStream: WriteStream {
_writableState: WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: true,
needDrain: false,
ending: true,
ended: true,
finished: true,
destroyed: true,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: true,
errorEmitted: false,
emitClose: false,
autoDestroy: false,
bufferedRequestCount: 0,
corkedRequestsFree: [Object]
},
writable: false,
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
path: '/var/folders/5g/f343vctd6hd7smyd5ybnfp4m0000gn/T/upload_4aebdbbee06344e12d8566dd706fd1e6',
fd: null,
flags: 'w',
mode: 438,
start: undefined,
autoClose: true,
pos: undefined,
bytesWritten: 13920,
closed: false
}
}
我的 C# 代码
public IAsyncResult BeginExecute()
{
// set authentication
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", BearerToken);
string url = "http://12915520.ngrok.io/api/organisations/" + OrganisationId + "/projects/" + ProjectId + "/process";
string response = null;
bool succesfullRequest = false;
try
{
using (FileStream fs = File.Open(@"C:\Users\X Y\Downloads\Invoice19.pdf", FileMode.Open, FileAccess.Read))
{
// send the content to the backend, parse results
HttpContent content = new StreamContent(fs);
MultipartFormDataContent formdata = new MultipartFormDataContent();
formdata.Add(content, "files", "Invoice19.pdf");
var result = client.PostAsync(url, formdata).Result;
response = result.Content.ReadAsStringAsync().Result;
succesfullRequest = result.IsSuccessStatusCode;
}
}
// I absolutely want to catch every exception and pass these along to the workflow
catch (Exception ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
throw;
}
// if something went wrong in the backend, throw an error
if (!succesfullRequest)
{
throw new Exception("Something went wrong during the upload process");
}
UploadResponse r = JsonConvert.DeserializeObject<UploadResponse>(response);
Console.WriteLine("uploadresponse:" + r.ToString());
// dirty solution: since we don't know how long the pipeline needs to process the upload, we'll be polling for a result
// since this is a poc this is a temporary solution, if this gets released this needs to be rewritten (maybe with webhooks)
//var polling = true;
//do
//{
// response = client.GetAsync(url + "/" + r.uploadId).Result.Content.ReadAsStringAsync().Result;
// if (response != "null")
// {
// polling = false;
// }
//} while (polling);
// Because we know that there is a response now, actually execute the request
//return client.GetAsync(url + "/" + r.uploadId);
return null;
}
我认为您需要更改使用 MultipartFormDataContent() 的方式
这对我有用
using (var content = new MultipartFormDataContent())
{
content.Add(new StreamContent(stream)
{
Headers =
{
ContentLength = stream.Length,
ContentType = new MediaTypeHeaderValue([your content type])
}
}, "[name ex: file]", "[file name ex: file.jpg]");
}
我通过这样做让它工作:
MultipartFormDataContent formdata = new MultipartFormDataContent()
foreach (var filePath in Files.Get(context))
{
// create filestream content
FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
HttpContent content = new StreamContent(fs);
string name = GetFileName(filePath);
content.Headers.Add("Content-Type", GetFileType(name));
formdata.Add(content, "files", name);
}
// send content to the backend and parse result
var resultPost = client.PostAsync(url, formdata).Result;
response = resultPost.Content.ReadAsStringAsync().Result;
succesfullRequest = resultPost.IsSuccessStatusCode;
基本上,我将内部内容的内容类型设置为任何文件类型,然后将外部内容的内容类型设置为 multipart/form-data(通过将其添加到 MultiPartFormData
)
由于我只支持有限数量的文件类型,所以我能够编写一个简单的函数:
private string GetFileType(string name)
{
char[] charSeparators = new char[] { '.' };
var splitName = name.Split(charSeparators);
string extension = splitName[1].ToLower();
switch (extension)
{
case "pdf":
return "application/pdf";
case "png":
return "image/png";
case "doc":
return "application/msword";
case "docx":
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
case "txt":
return "text/plain";
case "tif":
return "image/tif";
case "jpg":
return "image/jpg";
case "rtf":
return "application/rtf";
// default == not supported type, we don't set content type
default:
return "";
}
}
我正在尝试将文件流从 c# 发送到我的 js 后端。名称和路径已正确发送,但当我记录进入我的后端的文件时,类型似乎丢失了,我绝对需要文件类型,但我不知道如何传递它。有人可以帮我解决这个问题吗?
进来的对象:
File {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
size: 13920,
path: '/var/folders/5g/f343vctd6hd7smyd5ybnfp4m0000gn/T/upload_4aebdbbee06344e12d8566dd706fd1e6',
name: 'Invoice19.pdf',
type: null,
hash: null,
lastModifiedDate: 2020-03-17T14:11:04.812Z,
_writeStream: WriteStream {
_writableState: WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: true,
needDrain: false,
ending: true,
ended: true,
finished: true,
destroyed: true,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: true,
errorEmitted: false,
emitClose: false,
autoDestroy: false,
bufferedRequestCount: 0,
corkedRequestsFree: [Object]
},
writable: false,
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
path: '/var/folders/5g/f343vctd6hd7smyd5ybnfp4m0000gn/T/upload_4aebdbbee06344e12d8566dd706fd1e6',
fd: null,
flags: 'w',
mode: 438,
start: undefined,
autoClose: true,
pos: undefined,
bytesWritten: 13920,
closed: false
}
}
我的 C# 代码
public IAsyncResult BeginExecute()
{
// set authentication
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", BearerToken);
string url = "http://12915520.ngrok.io/api/organisations/" + OrganisationId + "/projects/" + ProjectId + "/process";
string response = null;
bool succesfullRequest = false;
try
{
using (FileStream fs = File.Open(@"C:\Users\X Y\Downloads\Invoice19.pdf", FileMode.Open, FileAccess.Read))
{
// send the content to the backend, parse results
HttpContent content = new StreamContent(fs);
MultipartFormDataContent formdata = new MultipartFormDataContent();
formdata.Add(content, "files", "Invoice19.pdf");
var result = client.PostAsync(url, formdata).Result;
response = result.Content.ReadAsStringAsync().Result;
succesfullRequest = result.IsSuccessStatusCode;
}
}
// I absolutely want to catch every exception and pass these along to the workflow
catch (Exception ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
throw;
}
// if something went wrong in the backend, throw an error
if (!succesfullRequest)
{
throw new Exception("Something went wrong during the upload process");
}
UploadResponse r = JsonConvert.DeserializeObject<UploadResponse>(response);
Console.WriteLine("uploadresponse:" + r.ToString());
// dirty solution: since we don't know how long the pipeline needs to process the upload, we'll be polling for a result
// since this is a poc this is a temporary solution, if this gets released this needs to be rewritten (maybe with webhooks)
//var polling = true;
//do
//{
// response = client.GetAsync(url + "/" + r.uploadId).Result.Content.ReadAsStringAsync().Result;
// if (response != "null")
// {
// polling = false;
// }
//} while (polling);
// Because we know that there is a response now, actually execute the request
//return client.GetAsync(url + "/" + r.uploadId);
return null;
}
我认为您需要更改使用 MultipartFormDataContent() 的方式
这对我有用
using (var content = new MultipartFormDataContent())
{
content.Add(new StreamContent(stream)
{
Headers =
{
ContentLength = stream.Length,
ContentType = new MediaTypeHeaderValue([your content type])
}
}, "[name ex: file]", "[file name ex: file.jpg]");
}
我通过这样做让它工作:
MultipartFormDataContent formdata = new MultipartFormDataContent()
foreach (var filePath in Files.Get(context))
{
// create filestream content
FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
HttpContent content = new StreamContent(fs);
string name = GetFileName(filePath);
content.Headers.Add("Content-Type", GetFileType(name));
formdata.Add(content, "files", name);
}
// send content to the backend and parse result
var resultPost = client.PostAsync(url, formdata).Result;
response = resultPost.Content.ReadAsStringAsync().Result;
succesfullRequest = resultPost.IsSuccessStatusCode;
基本上,我将内部内容的内容类型设置为任何文件类型,然后将外部内容的内容类型设置为 multipart/form-data(通过将其添加到 MultiPartFormData
)
由于我只支持有限数量的文件类型,所以我能够编写一个简单的函数:
private string GetFileType(string name)
{
char[] charSeparators = new char[] { '.' };
var splitName = name.Split(charSeparators);
string extension = splitName[1].ToLower();
switch (extension)
{
case "pdf":
return "application/pdf";
case "png":
return "image/png";
case "doc":
return "application/msword";
case "docx":
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
case "txt":
return "text/plain";
case "tif":
return "image/tif";
case "jpg":
return "image/jpg";
case "rtf":
return "application/rtf";
// default == not supported type, we don't set content type
default:
return "";
}
}