c # — .NET: загрузка файла на сервер с использованием http

У меня состояние бега .php скрипт, который попадает в URL и загружает один / несколько файлов .csv типа с уникальным token отправлено с ними (в теле AFAIK). Ниже приведен рабочий фрагмент:

PHP:

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

$ch = curl_init('http://demo.schooling.net/school/attendance');

$DirPath = "E:/Uploads/";

$ZKFiles=array();

if ($dh = opendir($DirPath))
{
while (($file = readdir($dh)) !== false)
{
if ($file == '.' || $file == '..')
{
continue;
}
$ZKFiles[]='@'.$DirPath.$file;
}
closedir($dh);
}
if(!empty($ZKFiles))
{
// Assign POST data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_FAILONERROR,false);
curl_setopt_custom_postfields($ch, array('Files[]'=>$ZKFiles,'token'=>'fe60313b0edfdfaf757f9744815454545'));
// Execute the handle
$execResult=curl_exec($ch);
if($execResult=== false)
{
echo 'Curl error: ' . curl_error($ch);
}
else
{
echo 'Operation completed without any errors';
echo $execResult;
}

}function curl_setopt_custom_postfields($ch, $postfields, $headers = null) {
$algos = hash_algos();
$hashAlgo = null;
foreach ( array('sha1', 'md5') as $preferred ) {
if ( in_array($preferred, $algos) ) {
$hashAlgo = $preferred;
break;
}
}
if ( $hashAlgo === null ) { list($hashAlgo) = $algos; }
$boundary =
'----------------------------' .
substr(hash($hashAlgo, 'cURL-php-multiple-value-same-key-support' . microtime()), 0, 12);

$body = array();
$crlf = "\r\n";
$fields = array();
foreach ( $postfields as $key => $value ) {
if ( is_array($value) ) {
foreach ( $value as $v ) {
$fields[] = array($key, $v);
}
} else {
$fields[] = array($key, $value);
}
}

//print_r($fields);die();
foreach ( $fields as $field ) {
list($key, $value) = $field;
if ( strpos($value, '@') === 0 ) {
preg_match('/^@(.*?)$/', $value, $matches);
list($dummy, $filename) = $matches;
$body[] = '--' . $boundary;
$body[] = 'Content-Disposition: form-data; name="' . $key . '"; filename="' . basename($filename) . '"';
$body[] = 'Content-Type: application/octet-stream';
$body[] = '';
$body[] = file_get_contents($filename);
} else {
$body[] = '--' . $boundary;
$body[] = 'Content-Disposition: form-data; name="' . $key . '"';
$body[] = '';
$body[] = $value;
}
}
$body[] = '--' . $boundary . '--';
$body[] = '';
//print_r($body);die();
$contentType = 'multipart/form-data; boundary=' . $boundary;
$content = join($crlf, $body);
$contentLength = strlen($content);

curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Length: ' . $contentLength,
'Expect: 100-continue',
'Content-Type: ' . $contentType,
));
//echo $content;die();
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
}
?>

Чтобы сделать это в .NET, что я пробовал до сих пор (все возможные способы)

Первый подход (используя WebClient):

[HttpPost]
public void SendFiles()
{
string fileToUpload = @"E:\Uploads\demo.csv";
string url ="http://demo.schooling.net/school/attendance";
using (var client = new WebClient())
{
//sending token and then uplaoding file
System.Collections.Specialized.NameValueCollection postData =
new System.Collections.Specialized.NameValueCollection()
{
{ "token", "fe60313b0edfdfaf757f9744815454545" }
};
string pagesource = Encoding.UTF8.GetString(client.UploadValues(url, "POST", postData));

//string authInfo = Convert.ToBase64String(Encoding.Default.GetBytes("fe60313b0edfdfaf757f9744815454545"));
client.Headers["token"] = "fe60313b0edfdfaf757f9744815454545";
client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
byte[] result = client.UploadFile(url, fileToUpload);
string responseAsString = Encoding.Default.GetString(result);
}
}

Это не отправило токен на URL, поэтому страница перенаправляется на страницу входа.

Второй подход (используя .NET MultipartDataContent)

string fileUpload = @"E:\Uploads\demo.csv";
string uri = "http://demo.schooling.net/school/attendance";
//Using built-in MultipartFormDataContent
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form1 = new MultipartFormDataContent();
FileStream fs = System.IO.File.OpenRead(fileUpload);
var streamContent = new StreamContent(fs);

var Content = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
Content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
//Add token here first
form1.Add(new StringContent("fe60313b0edfdfaf757f9744815454545"), "token");
form1.Add(Content, "csv", Path.GetFileName(fileUpload));
var response = httpClient.PostAsync(uri, form1).Result;

Это не удалось и поэтому привело меня к третьей попытке. (токен не был отправлен)

Третий подход (используя cutom MultipartForm описано Вот)

//Using Custom MultipartForm
MultipartForm form = new MultipartForm(url);
form.SetField("token", "fe60313b0edfdfaf757f9744815454545");

form.SendFile(@"E:\Uploads\demo.csv");

MultiPartForm.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Net;

namespace Helpers
{
/// <summary>
/// Allow the transfer of data files using the W3C's specification
/// for HTTP multipart form data. Microsoft's version has a bug
/// where it does not format the ending boundary correctly.
/// Original version written by Gregory Prentice : [email protected]
/// See: http://www.c-sharpcorner.com/UploadFile/gregoryprentice/DotNetBugs12062005230632PM/DotNetBugs.aspx
/// </summary>
public class MultipartForm
{
/// <summary>
/// Holds any form fields and values that you
/// wish to transfer with your data.
/// </summary>
private Hashtable coFormFields;

/// <summary>
/// Used mainly to avoid passing parameters to other routines.
/// Could have been local to sendFile().
/// </summary>
protected HttpWebRequest coRequest;

/// <summary>
/// Used if we are testing and want to output the raw
/// request, minus http headers, out to a file.
/// </summary>
private Stream coFileStream;

/// <summary>
/// Difined to build the form field data that is being
/// passed along with the request.
/// </summary>
private static string CONTENT_DISP = "Content-Disposition: form-data; name=";

/// <summary>
/// Allows you to specify the specific version of HTTP to use for uploads.
/// The dot NET stuff currently does not allow you to remove the continue-100 header
/// from 1.1 and 1.0 currently has a bug in it where it adds the continue-100. MS
/// has sent a patch to remove the continue-100 in HTTP 1.0.
/// </summary>
public Version TransferHttpVersion { get; set; }

/// <summary>
/// Used to change the content type of the file being sent.
/// Currently defaults to: text/xml. Other options are
/// text/plain or binary
/// </summary>
public string FileContentType { get; set; }

/// <summary>
/// Initialize our class for use to send data files.
/// </summary>
/// <param name="url">The web address of the recipient of the data transfer.</param>
public MultipartForm(string url)
{
URL = url;
coFormFields = new Hashtable();
ResponseText = new StringBuilder();
BufferSize = 1024 * 10;
BeginBoundary = "ou812--------------8c405ee4e38917c";
TransferHttpVersion = HttpVersion.Version11;
//FileContentType = "text/xml";
FileContentType = "text/csv";
}
//---------- BEGIN PROPERTIES SECTION ----------
private string _BeginBoundary;
/// <summary>
/// The string that defines the begining boundary of
/// our multipart transfer as defined in the w3c specs.
/// This method also sets the Content and Ending
/// boundaries as defined by the w3c specs.
/// </summary>
public string BeginBoundary
{
get { return _BeginBoundary; }
set
{
_BeginBoundary = value;
ContentBoundary = "--" + BeginBoundary;
EndingBoundary = ContentBoundary + "--";
}
}

/// <summary>
/// The string that defines the content boundary of
/// our multipart transfer as defined in the w3c specs.
/// </summary>
protected string ContentBoundary { get; set; }

/// <summary>
/// The string that defines the ending boundary of
/// our multipart transfer as defined in the w3c specs.
/// </summary>
protected string EndingBoundary { get; set; }

/// <summary>
/// The data returned to us after the transfer is completed.
/// </summary>
public StringBuilder ResponseText { get; set; }

/// <summary>
/// The web address of the recipient of the transfer.
/// </summary>
public string URL { get; set; }

/// <summary>
/// Allows us to determine the size of the buffer used
/// to send a piece of the file at a time out the IO
/// stream. Defaults to 1024 * 10.
/// </summary>
public int BufferSize { get; set; }

//---------- END PROPERTIES SECTION ----------

/// <summary>
/// Used to signal we want the output to go to a
/// text file verses being transfered to a URL.
/// </summary>
/// <param name="path"></param>
public void SetFilename(string path)
{
coFileStream = new System.IO.FileStream(path, FileMode.Create, FileAccess.Write);
}
/// <summary>
/// Allows you to add some additional field data to be
/// sent along with the transfer. This is usually used
/// for things like userid and password to validate the
/// transfer.
/// </summary>
/// <param name="key">The form field name</param>
/// <param name="str">The form field value</param>
public void SetField(string key, string str)
{
coFormFields[key] = str;
}
/// <summary>
/// Determines if we have a file stream set, and returns either
/// the HttpWebRequest stream of the file.
/// </summary>
/// <returns></returns>
public virtual Stream GetStream()
{
Stream stream;
if (null == coFileStream)
stream = coRequest.GetRequestStream();
else
stream = coFileStream;
return stream;
}
/// <summary>
/// Here we actually make the request to the web server and
/// retrieve it's response into a text buffer.
/// </summary>
public virtual void GetResponse()
{
if (null == coFileStream)
{
Stream stream;
WebResponse response;
try
{
response = coRequest.GetResponse();
}
catch (WebException web)
{
response = web.Response;
}
if (null != response)
{
stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
string str;
ResponseText.Length = 0;
while ((str = sr.ReadLine()) != null)
ResponseText.Append(str);
response.Close();
}
else
throw new Exception("MultipartForm: Error retrieving server response");
}
}
/// <summary>
/// Transmits a file to the web server stated in the
/// URL property. You may call this several times and it
/// will use the values previously set for fields and URL.
/// </summary>
/// <param name="filename">The full path of file being transfered.</param>
public void SendFile(string filename)
{
// The live of this object is only good during
// this function. Used mainly to avoid passing
// around parameters to other functions.
coRequest = (HttpWebRequest)WebRequest.Create(URL);
// Set use HTTP 1.0 or 1.1.
coRequest.ProtocolVersion = TransferHttpVersion;
coRequest.Method = "POST";
coRequest.ContentType = "multipart/form-data; boundary=" + BeginBoundary;
coRequest.Headers.Add("Cache-Control", "no-cache");
coRequest.KeepAlive = true;
string strFields = GetFormfields();
string strFileHdr = GetFileheader(filename);
string strFileTlr = GetFiletrailer();
FileInfo info = new FileInfo(filename);
coRequest.ContentLength = strFields.Length +
strFileHdr.Length +
strFileTlr.Length +
info.Length;
System.IO.Stream io;
io = GetStream();
WriteString(io, strFields);
WriteString(io, strFileHdr);
this.WriteFile(io, filename);
WriteString(io, strFileTlr);
GetResponse();
io.Close();
// End the life time of this request object.
coRequest = null;
}
/// <summary>
/// Mainly used to turn the string into a byte buffer and then
/// write it to our IO stream.
/// </summary>
/// <param name="stream">The io stream for output.</param>
/// <param name="str">The data to write.</param>
public void WriteString(Stream stream, string str)
{
byte[] postData = System.Text.Encoding.ASCII.GetBytes(str);
stream.Write(postData, 0, postData.Length);
}
/// <summary>
/// Builds the proper format of the multipart data that
/// contains the form fields and their respective values.
/// </summary>
/// <returns>The data to send in the multipart upload.</returns>
public string GetFormfields()
{
string str = "";
IDictionaryEnumerator myEnumerator = coFormFields.GetEnumerator();
while (myEnumerator.MoveNext())
{
str += ContentBoundary + "\r\n" +
CONTENT_DISP + '"' + myEnumerator.Key + "\"\r\n\r\n" +
myEnumerator.Value + "\r\n";
}
return str;
}
/// <summary>
/// Returns the proper content information for the
/// file we are sending.
/// </summary>
/// <remarks>
/// Hits Patel reported a bug when used with ActiveFile.
/// Added semicolon after sendfile to resolve that issue.
/// Tested for compatibility with IIS 5.0 and Java.
/// </remarks>
/// <param name="filename"></param>
/// <returns></returns>
public string GetFileheader(string filename)
{
return ContentBoundary + "\r\n" +
CONTENT_DISP +
"\"sendfile\"; filename=\"" +
Path.GetFileName(filename) + "\"\r\n" +
"Content-type: " + FileContentType + "\r\n\r\n";
}
/// <summary>
/// Creates the proper ending boundary for the multipart upload.
/// </summary>
/// <returns>The ending boundary.</returns>
public string GetFiletrailer()
{
return "\r\n" + EndingBoundary;
}
/// <summary>
/// Reads in the file a chunck at a time then sends it to the
/// output stream.
/// </summary>
/// <param name="stream">The io stream to write the file to.</param>
/// <param name="filename">The name of the file to transfer.</param>
public void WriteFile(Stream stream, string filename)
{
using (FileStream readIn = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
readIn.Seek(0, SeekOrigin.Begin); // move to the start of the file
byte[] fileData = new byte[BufferSize];
int bytes;
while ((bytes = readIn.Read(fileData, 0, BufferSize)) > 0)
{
// read the file data and send a chunk at a time
stream.Write(fileData, 0, bytes);
}
}
}
}
}

Без удачи, но с большой терпимостью приходит четвертая попытка (в этом подходе также не было отправлено никакого жетона)

Четвертый подход (используя HttpClient)

using (var client = new HttpClient())
{
using (var multipartFormDataContent = new MultipartFormDataContent())
{
var values = new[]
{

new KeyValuePair<string, string>("token", "fe60313b0edfdfaf757f9744815454545")
//other values
};

foreach (var keyValuePair in values)
{
multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
String.Format("\"{0}\"", keyValuePair.Key));
}

multipartFormDataContent.Add(new ByteArrayContent(System.IO.File.ReadAllBytes(@"E:\\Uploads\\demo.csv")),
'"' + "File" + '"',
'"' + "democollege.csv" + '"');
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", "fe60313b0edfdfaf757f9744815454545");
var requestUri = "http://demo.schooling.net/school/attendance";
var result = client.PostAsync(requestUri, multipartFormDataContent).Result;
}
}

Это также сбило меня с ног, опять же без токена и, в конце концов, файл не был загружен

Пятый подход (используя HttpWebRequest)

   public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.AllowAutoRedirect = false;
// wr.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Your Oauth token");
wr.Headers.Add("Authorization", "Basic " + "fe60313b0edfdfaf757f9744815454545");
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
var result = reader2.ReadToEnd();
}
catch (Exception ex)
{
// System.Windows.MessageBox.Show("Error occurred while converting file", "Error!");
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}

а затем вызвать этот метод:

string fileToUpload = @"E:\Uploads\demo.csv";
string url = "http://demo.schooling.net/school/attendance";
NameValueCollection nvc = new NameValueCollection();
nvc.Add("token", "fe60313b0edfdfaf757f9744815454545");
HttpUploadFile(url, fileToUpload, "file", "text/csv", nvc);

Это также не удалось, хотя я получаю данные формы. (картинка прилагается, используя одну из попыток выше)
введите описание изображения здесь

Добавив эту строку в PHP сценарий:

 ...$body[] = '';
print_r($body);die();

Я вижу это в браузере:

Array ( [0] => Array
( [0] => Files[]
[1] => @E:/Uploads/demo.csv )
[1] => Array ( [0] => token
[1] => fe60313b0edfdfaf757f9744815454545) )

Добавьте строку ниже в php-скрипте:

print_r($body); die();

в конце function curl_setopt_custom_postfields($ch, $postfields, $headers = null); Функция я мог видеть это в браузере:

Array ( [0] => ------------------------------3c935d382987
[1] => Content-Disposition: form-data; name="Files[]"; filename="demo.csv"[2] => Content-Type: application/octet-stream
[3] =>
[4] => No,Name,Time,Verify,Mach,Ex,checktype,sid,code,Date 22364,22364,12/8/2017 10:28,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22365,22365,12/8/2017 9:29,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22366,22366,12/8/2017 10:59,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22369,22369,12/8/2017 11:58,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22364,22364,11/7/2017 10:28,Fingerpint,democollege-1-1,,I,1,0,11/7/2017 22365,22365,11/7/2017 9:29,Fingerpint,democollege-1-1,,I,1,0,11/7/2017 22366,22366,11/7/2018 10:59,Fingerpint,democollege-1-1,,I,1,0,11/7/2017 22369,22369,11/7/2018 11:58,Fingerpint,democollege-1-1,,I,1,0,11/7/2017
[5] => ------------------------------3c935d382987
[6] => Content-Disposition: form-data; name="token"[7] =>
[8] => fe60313b0edfdfaf757f9744815454545
[9] => ------------------------------3c935d382987--
[10] => )

Скрипач:

введите описание изображения здесь

14

Решение

.Net Web Api File; Загрузка, загрузка, просмотр изображений и сервисы SendCloud

Web.config

<appSettings>

<!--FileService-->
<add key="ftpUserName" value="fooUserName" />
<add key="ftpPassword" value="fooPass" />

<!--FileController-->
<add key="fileServiceLocalPath" value="~/App_Data/Upload" />
<add key="fileServiceStoragePath" value="fooFtpAddress" />
<add key="useCloud" value="false" />

</appSettings>

Файловый контроллер с аутентификацией

[Authorize]
[RoutePrefix("api/File")]

public class FileController : ApiController
{
IFileService fileService = null;
public FileController(IFileService _fileService)
{
fileService = _fileService;
}

[Route("Upload"), HttpPost]
public async Task<IHttpActionResult> Upload()
{
#region Condition

if (!Request.Content.IsMimeMultipartContent())
return Content(HttpStatusCode.UnsupportedMediaType, Messages.FUW0001);
#endregion

/// `localPath` and `useCloud` is get from Web.Config.
string localPath = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["fileServiceLocalPath"]);
bool useCloud = Convert.ToBoolean(ConfigurationManager.AppSettings["useCloud"]);

var provider = new MultipartFormDataStreamProvider(localPath);

try
{
/// Loads the files into the local storage.
await Request.Content.ReadAsMultipartAsync(provider);

/// Check is exist valid file.
if (provider.FileData.Count == 0)
return BadRequest(Messages.FUE0001 /*Message Type FUE001 = File Not Found */);

IList<FileDto> modelList = new List<FileDto>();

foreach (MultipartFileData file in provider.FileData)
{
string originalName = file.Headers.ContentDisposition.FileName;
if (originalName.StartsWith("\"") && originalName.EndsWith("\""))
{
originalName = originalName.Trim('"');
}
if (originalName.Contains(@"/") || originalName.Contains(@"\"))
{
originalName = Path.GetFileName(originalName);
}

/// File information storage my database.
FileDto fileDto = new FileDto
{
OriginalName = Path.GetFileNameWithoutExtension(originalName),
StorageName = Path.GetFileName(file.LocalFileName),
Extension = Path.GetExtension(originalName).ToLower().Replace(".", ""),
Size = new FileInfo(file.LocalFileName).Length
};

modelList.Add(fileDto);
}

if (useCloud)
await fileService.SendCloud(modelList,localPath);

await fileService.Add(modelList, IdentityClaimsValues.UserID<Guid>());

return Ok(Messages.Ok);
}
catch (Exception exMessage)
{
return Content(HttpStatusCode.InternalServerError, exMessage);
}
}

[   Route("Download"), HttpGet]
public async Task<IHttpActionResult> Download(Guid id)
{
/// Get file information my database
var model = await fileService.GetByID(id);

if (model == null)
return BadRequest();

/// `localPath` is get from Web.Config.
string localPath = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["fileServiceLocalPath"]);

string root = localPath + "\\" + model.StorageName;

byte[] fileData = File.ReadAllBytes(root);
var stream = new MemoryStream(fileData, 0, fileData.Length);

var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.ToArray())
};

response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = model.OriginalName + "." + model.Extension,
Size=model.Size
};

response.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");

IHttpActionResult result = ResponseMessage(response);
return result;
}

[Route("ImageReview"), HttpGet]
public async Task<IHttpActionResult> ImageReview(Guid id)
{
/// Get file information my database
var model = await fileService.GetByID(id);

if (model == null)
return BadRequest();

/// `localPath` is get from Web.Config.
string localPath = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["fileServiceLocalPath"]);

string root = localPath + "\\" + model.StorageName;

byte[] fileData = File.ReadAllBytes(root);
var stream = new MemoryStream(fileData, 0, fileData.Length);

var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(stream)
};

response.Content.Headers.ContentType =
new MediaTypeHeaderValue("image/"+ model.Extension);

IHttpActionResult result = ResponseMessage(response);

return result;
}
}

Файловая служба

public interface IFileService
{
Task SendCloud(IList<FileDto> modelList, string localPath);
}

public class FileService : IFileService
{
public Task SendCloud(IList<FileDto> modelList,string localPath)
{
/// `ftpUserName`, `ftpPassword` and `storagePath` is get from Web.Config.
string ftpUserName = ConfigurationManager.AppSettings["ftpUserName"];
string ftpPassword = ConfigurationManager.AppSettings["ftpPassword"];
string storagePath = ConfigurationManager.AppSettings["fileServiceStoragePath"];

/// Uploaded files are sent to the cloud server.
foreach (var model in modelList)
{
FtpWebRequest req = (FtpWebRequest)WebRequest.Create(storagePath + model.StorageName);

req.UseBinary = true;
req.Method = WebRequestMethods.Ftp.UploadFile;
req.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
byte[] fileData = File.ReadAllBytes(localPath + "\\" + model.StorageName);
req.ContentLength = fileData.Length;

Stream reqStream = req.GetRequestStream();
reqStream.Write(fileData, 0, fileData.Length);
reqStream.Close();
}

return Task.CompletedTask;
}

}

Это изображение для сборки.

Запрос обзора изображения для скрипача

отклик

6

Другие решения

Я думаю твой HttpClient с MultipartFormDataContent подход должен работать

просто нужно искать входные имена, пожалуйста, попробуйте следующее

HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();

string filename = @"E:\Uploads\demo.csv", filename2 = @"E:\Uploads\demo2.csv", url = "http://demo.schooling.net/school/attendance", token = "fe60313b0edfdfaf757f9744815454545";
byte[] bytes = System.IO.File.ReadAllBytes(filename);// Keep `token` here, no quote escaping
form.Add(new StringContent(token), "token");

// Keep `Files[]` here
form.Add(new ByteArrayContent(bytes), "Files[]", Path.GetFileName(filename));

// To add 2nd file, keep the input name as `Files[]`
bytes = System.IO.File.ReadAllBytes(filename2);
form.Add(new ByteArrayContent(bytes), "Files[]", Path.GetFileName(filename2));

var result = httpClient.PostAsync(url, form).Result;
0

По вопросам рекламы [email protected]