Получить вложение файла из MMS через контроллер ASP.NET MVC

Я пробую сервис Twilio для взаимодействия с людьми через SMS/MMS. Я примерно понял, как отправлять MMS-сообщения, чтобы начать «разговор», и, похоже, это работает хорошо. Однако сейчас я пытаюсь создать систему, которая будет отвечать на входящие сообщения на мой тестовый номер с поддержкой SMS/MMS. Я работаю с одним из примеров, которые я нашел на сайте документации Twilio, для создания веб-службы ASP.NET MVC для обработки диалога (VB.NET):

Imports System.Web.Mvc
Imports Twilio.AspNet.Common
Imports Twilio.AspNet.Mvc
Imports Twilio.TwiML

Namespace Controllers
    Public Class SMSController
        Inherits TwilioController

        ' GET: SMS
        Function Index(ByVal IncomingSMS As SmsRequest) As TwiMLResult
            Dim SMSResponse As New MessagingResponse
            Dim SMSMessage As String = IncomingSMS.Body
            Dim JediCode As String = "There is no emotion, there is peace."
            Dim SithCode As String = "Peace is a lie. There is only Passion."

            JediCode += vbCrLf & "There is no ignorance, there is knowledge."
            JediCode += vbCrLf & "There is no passion, there is serenity."
            JediCode += vbCrLf & "There is no chaos, there is harmony."
            JediCode += vbCrLf & "There is no death, there is the Force."

            SithCode += vbCrLf & "Through Passion, I gain Strength."
            SithCode += vbCrLf & "Through Strength, I gain Power."
            SithCode += vbCrLf & "Through Power, I gain Victory."
            SithCode += vbCrLf & "Through Victory my chains are Broken."
            SithCode += vbCrLf & "The Force shall free me."

            If SMSMessage IsNot Nothing Then
                If SMSMessage.ToUpper.Trim = "JEDI" Then
                    SMSResponse.Message(JediCode)
                ElseIf SMSMessage.ToUpper.Trim = "SITH" Then
                    SMSResponse.Message(SithCode)
                Else
                    SMSResponse.Message("Ahsoka? Is that you?")
                End If
            Else
                SMSResponse.Message("What did you want to know?")
            End If

            Return TwiML(SMSResponse)
        End Function
    End Class
End Namespace

Да, это все просто «игровые» вещи, которые я использую для тестирования и в конечном итоге буду заменен чем-то более подходящим для этой цели, но я хочу попытаться разобраться во всем этом, прежде чем я слишком углублюсь в реальность вещей. .

Я настроил сайт на своем сервере IIS, зарегистрировал DNS и даже настроил свой SSL-сертификат. Кажется, все отлично работает с моим простым тестированием до сих пор, но есть пара вещей, которые я до сих пор не смог понять, и я надеюсь, что кто-то здесь может указать мне правильное направление.

Я задам каждый по отдельности, но вот первый: как мне получить вложение из MMS-сообщения?

Я хотел бы иметь возможность получать PDF-файлы (и, возможно, файлы других типов) и передавать их по электронной почте соответствующему лицу или отделу. Я знаю, как отправлять сообщения по электронной почте, но мне не удалось найти соответствующую документацию о том, как получить вложения в MMS-сообщении, чтобы фактически включить их в этот процесс электронной почты.

Когда я пытаюсь получить доступ к свойствам объекта IncomingSMS (SmsRequest), я не нахожу ссылки на Media ни в одном из них — ни NumMedia, ни MediaUri, ничего. Кажется, не существует типа объекта MmsRequest (во всяком случае, я его еще не нашел).

Что я упускаю из виду, чтобы иметь возможность получить PDF-файл, который я отправил на свой тестовый номер, для дальнейшей обработки? Должен ли я изменить определение метода, чтобы принять объект как MessageResource или что-то в этом роде?

Обновлено: я забыл упомянуть, что я проверил консоль Twilio и увидел, что сообщение, по-видимому, было успешно получено с вложением, поэтому я знаю, что по крайней мере эта часть работает правильно.

Я задал второй связанный вопрос, который идет вместе с этим, чтобы помочь «доработать» некоторые вещи для наших целей.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
104
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Используемый вами класс SmsRequest взят из вспомогательной библиотеки Twilio для ASP.NET, цель которой — упростить интеграцию Twilio в ASP.NET. Однако SmsRequest и другие классы не охватывают все возможные параметры веб-перехватчика. Если в классе отсутствуют параметры, вы все равно можете получить параметры вручную, а не полагаться на привязку модели MVC.

На основе этого примера C# я создал пример VB.NET, чтобы показать, как получать и сохранять входящие файлы MMS:

Imports System.IO
Imports System.Net.Http
Imports System.Threading.Tasks
Imports MimeTypes
Imports Twilio.AspNet.Mvc
Imports Twilio.TwiML
Imports Twilio.TwiML.Messaging

Public Class HomeController
    Inherits TwilioController

    Shared httpClient As HttpClient = New HttpClient

    Async Function Index() As Task(Of TwiMLResult)
        Dim response As New MessagingResponse
        Dim message As New Message

        Dim numMedia = Short.Parse(If(Request.Form.Get("NumMedia"), 0))
        If numMedia = 0 Then
            response.Message("No file received.")
            Return TwiML(response)
        End If

        For mediaIndex As Integer = 0 To numMedia - 1
            Dim mediaUrl = Request.Form.Get($"MediaUrl{mediaIndex}")
            Dim contentType = Request.Form.Get($"MediaContentType{mediaIndex}")
            Dim saveFilePath = Server.MapPath(String.Format(
                "~/App_Data/{0}{1}",
                Path.GetFileName(mediaUrl),
                MimeTypeMap.GetExtension(ContentType)
            ))
            Await DownloadUrlToFileAsync(mediaUrl, saveFilePath)
        Next

        response.Message("File received.")
        Return TwiML(response)
    End Function

    Private Async Function DownloadUrlToFileAsync(mediaUrl As String, saveFilePath As String) As Task
        Dim Response = Await httpClient.GetAsync(mediaUrl)
        Dim httpStream = Await Response.Content.ReadAsStreamAsync()
        Using fileStream As Stream = IO.File.Create(saveFilePath)
            Await httpStream.CopyToAsync(fileStream)
            Await fileStream.FlushAsync()
        End Using
    End Function


End Class

Вероятно, вы можете немного упростить код, предполагая, что по MMS будет отправлен только один файл, но это хорошая идея, чтобы обрабатывать и другие случаи.

Чтобы получить правильное расширение файла, я использую это Библиотека MimeTypeMap, но можно накатить собственное решение.

По умолчанию файлы из входящих MMS общедоступны по MediaUrl{mediaIndex} URL-адресу, но рекомендуется включить базовую аутентификацию для этих медиафайлов.

Если вы включаете обычную аутентификацию для медиафайлов, вам необходимо добавить заголовок аутентификации в HTTP-запросы, например:

Imports System.IO
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Threading.Tasks
Imports MimeTypes
Imports Twilio.AspNet.Mvc
Imports Twilio.TwiML
Imports Twilio.TwiML.Messaging

Public Class HomeController
    Inherits TwilioController

    Shared httpClient As HttpClient = CreateHttpClient()
    Private Shared Function CreateHttpClient() As HttpClient
        Dim client As New HttpClient
        Dim appSettings As NameValueCollection = ConfigurationManager.AppSettings
        If Boolean.Parse(If(appSettings.Get("TwilioUseBasicAuthForMedia"), False)) Then
            Dim authString = $"{appSettings.Get("TwilioAccountSid")}:{appSettings.Get("TwilioAuthToken")}"
            authString = Convert.ToBase64String(Encoding.ASCII.GetBytes(authString))
            client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Basic", authString)
        End If

        Return client
    End Function

    ...

End Class

Я получаю TwilioUseBasicAuthForMedia, TwilioAccountSid и TwilioAuthToken из настроек приложения Web.config.

(Убедитесь, что вы не проверяете эти секреты в системе управления версиями, а используйте вместо этого UserSecretsConfigBuilder, чтобы безопасно установить секреты).

Вот исходный код на GitHub.


Вы можете отправить сообщение о проблеме GitHub и/или PR, чтобы добавить поддержку этих отсутствующих параметров в SmsRequest. Хотя это будет не так просто, как обычная привязка модели, потому что количество параметров увеличивается по мере того, как больше файлов отправляется по MMS.

Спасибо. Я также связался со службой поддержки и получил предложение использовать платформу Studio для некоторых других моих требований к реализации, но я все еще рассматриваю эту сборку, поскольку у меня все «на месте».

G_Hosa_Phat 21.09.2022 16:01

Понятно! Дайте мне знать, если мне нужно что-то уточнить. Удачи!

Swimburger 21.09.2022 17:58

Я включил код извлечения мультимедиа в мой код контроллера MVC выше и протестировал его, загрузив файл. Он успешно сохранил файл по моему локальному пути. Однако у меня есть тот же код для ответа пользователю (и тот же URL-адрес контроллера MVC в консоли Twilio), но мой клиент обмена сообщениями получил «общий» ответ для настройки URL-адреса SMS номера из Twilio вместо тех, которые определены в моем контроллере. . Кроме того, у меня есть сообщение 11200 HTTP retrieval failure в журналах. Я позаботился о том, чтобы опубликовать все свои изменения, но я должен что-то упустить.

G_Hosa_Phat 21.09.2022 18:43

Может быть, в вашем коде чего-то не хватает, что может привести к неправильной работе AsyncAwait? Это может привести к некоторому странному поведению. Не стесняйтесь делиться кодом, используя Pastebin или что-то в этом роде.

Swimburger 21.09.2022 20:21

Большое спасибо. Этот Gist — это то, чем я сейчас пользуюсь. Как я уже сказал, файлы извлекаются, но «соответствующий» ответ What did you want to know? (поскольку тела сообщения нет) не отправляется обратно. Кроме того, он не создает файл журнала, который я указал для устранения неполадок. Я отключил настраиваемые отчеты об ошибках ASP.NET (на данный момент), и когда я углубляюсь в ошибку на консоли Twilio, я вижу в ответе сообщение с указанием Username can not be null.

G_Hosa_Phat 21.09.2022 20:46

Я продолжу отвечать в Gist, а не здесь, поскольку ошибки больше не связаны с исходным вопросом.

Swimburger 21.09.2022 21:07

Другие вопросы по теме